#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "crc16.h"
#include <QMessageBox>
#include <QTime>
#include <QInputDialog>
#include <manualconfirmationdlg.h>
#include "sys_config.h"
#include <QFile>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QPalette>
#include "settingdialog.h"
#include "MyMessageBox.h"

int ModbusReadInputBits(int addr, int nb, uint8_t *dest);
int ModbusReadRegisters(int addr, int nb, uint16_t *dest);
int ModbusWriteRegister(int addr, uint16_t val);
int ModbusReadInputRegisters(int addr, int nb, uint16_t *dest);
int ModbusReadFactoryRegisters(int addr, int nb, uint16_t *dest);
int ModbusWriteFactoryRegisters(int addr, int nb, uint16_t *val);
QByteArray GetSerialPortRecvBuf(void);
void ClearSerialPortRecvBuf(void);

QSerialPort *serial = nullptr;//全局的串口对象

DeviceData dev_data;
QMutex dev_mutex;
QMutex serial_mutex;
ComStr com;

static int32_t g_keep_setting_flag = 0;

// 依次为电解片规格对应SI、SJ、SV有效范围


const float electrolytic_sj_range[ELECTROLYTIC_STRIP_TYPE][2] = {
    {0.5, 1.8},     // 10
    {1.0, 2.0},     // 14
    {1.4, 2.4},     // 16
    {1.8, 3.0},     // 22
    {2.6, 3.2},     // 28
    {2.4, 3.0},     // 30
    {2.6, 3.2},     // 34
};

const float electrolytic_si_range[ELECTROLYTIC_STRIP_TYPE][2] = {
    {3.0, 6.5},     // 10
    {3.8, 6.5},     // 14
    {4.5, 7.8},     // 16
    {6.5, 10.2},     // 22
    {7.5, 10.3},    // 28
    {8.2, 10.4},    // 30
    {9.5, 10.5},    // 34
};

const float electrolytic_sv_range[ELECTROLYTIC_STRIP_TYPE][2] = {
    {4.0, 7.5},     // 10
    {5.2, 6.5},   // 14
    {4.8, 8.5},   // 16
    {6.5, 10.6},   // 22
    {8.5, 12.5},   // 28
    {8.5, 10.5},   // 30
    {9.5, 12.5},   // 34
};

void OsSleep(unsigned int msec)
{
    QTime reachTime = QTime::currentTime().addMSecs(msec);
//    qDebug("OsSleep");
    while (QTime::currentTime() < reachTime) {
//        qDebug()
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
    }
//    QTime _Timer = QTime::currentTime();

//    QTime _NowTimer;
//    do{
//              _NowTimer=QTime::currentTime();
//              QCoreApplication::processEvents(QEventLoop::AllEvents);
//    }while (_Timer.msecsTo(_NowTimer)<=msec);
}

//7A A7 01 F8 0D 0A 停止
//7A A7 01 FB 0D 0A 前进
//7A A7 01 FC 0D 0A 后退
//7A A7 01 FD 0D 0A 左转
//7A A7 01 FE 0D 0A 右转
//7A A7 01 F9 0D 0A 池底
//7A A7 01 FA 0D 0A 池壁

void ModbusCommunication(void *arg) {
    MainWindow *mw = (MainWindow *)arg;
    mw->GetDeviceData();
    mw->TestStepCtrl();
    //mw->ModbusWriteRegister(0x0000, 10);    // 进入工厂测试模式
    //qDebug("ModbusCommunication");
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //demoThread = new QDemoThread(this);
    setWindowTitle(TITLE_STR);

//    //查找可用的串口
//    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
//    {
//        QSerialPort serial;
//        serial.setPort(info);

//        if(serial.open(QIODevice::ReadWrite))
//        {
//            ui->portBox->addItem(serial.portName());
//            qDebug()<<"port ok:"<<serial.portName();
//            serial.close();
//        }else{
//            qDebug()<<"port err:"<<serial.portName();
//        }
//    }
    InitSerialPortList();

    //设置波特率下拉菜单的第0项默认值
#if 0
    ui->baudBox->setCurrentIndex(3);
    ui->dataBox->setCurrentIndex(2);
    ui->checkBox->setCurrentIndex(0);
    ui->stopBox->setCurrentIndex(0);
#endif
    ui->portBox->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14-2));

    ui->OpenSerialButton->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));
    ui->RefreshSerialButton->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));

    //ui->comboBox->addItem(tr("10g"));
    ui->comboBox->setCurrentIndex(1);
    ui->comboBox->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));

    ui->label_control_mode->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));
    ui->comboBox_control_mode->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));
    ui->comboBox_control_mode->setCurrentIndex(0);

    ui->TestButton->setText("START");
    ui->TestButton->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->TestButton->setStyleSheet("color: rgb(134, 134, 134)");
    ui->TestButton->setStyleSheet("background-color: rgb(204, 204, 204)");
    ui->TestButton->setEnabled(false);
    ui->TestButton->hide();

    ui->label_judge_time->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_judge_time->hide();

    ui->label_soft_version->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_soft_version->hide();
    ui->label_product_type->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_product_type->hide();

    //ui->label_led->hide();

    InitTextBrowser();

    ui->label_com->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));
    ui->label_size_select->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_14));

    ui->label_key->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_key1->setFont(QFont(SYS_FONT_TYPE, 20));
    ui->label_key2->setFont(QFont(SYS_FONT_TYPE, 20));
    ui->label_key3->setFont(QFont(SYS_FONT_TYPE, 20));
    ui->label_key4->setFont(QFont(SYS_FONT_TYPE, 20));
    ui->label_key5->setFont(QFont(SYS_FONT_TYPE, 20));

    ui->label_buzzer->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_motor->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));

    ui->label_uint_A->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_C->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_V->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_V->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_g->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_A2->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_C2->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_uint_mv->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_ph->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_orp->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_temp1->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_temp2->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_sj->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_si->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_sv->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_POINT->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_point_state->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_WIFI->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_wifi_state->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_TIME->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_time_state->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_rs485->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_rs485_state->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_sr->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_sr_state->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_rc->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_rc_state->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));
    ui->label_SIZE->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_16));


    ui->lcdNumber_4->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_4->setFont(QFont(SYS_FONT_TYPE, LCD_NUM_FONT_SIZE));
    ui->lcdNumber_3->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_3->setFont(QFont(SYS_FONT_TYPE, LCD_NUM_FONT_SIZE));
    ui->lcdNumber_2->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_2->setFont(QFont(SYS_FONT_TYPE, LCD_NUM_FONT_SIZE));
    ui->lcdNumber->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_5->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_6->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_7->setStyleSheet("background-color: rgb(255, 255, 255)");
    ui->lcdNumber_8->setStyleSheet("background-color: rgb(255, 255, 255)");

    ui->lcdNumber_4->setDecMode();
    ui->lcdNumber_3->setDecMode();
    ui->lcdNumber_2->setDecMode();
    ui->lcdNumber->setDecMode();
    ui->lcdNumber_5->setDecMode();
    ui->lcdNumber_6->setDecMode();
    ui->lcdNumber_7->setDecMode();
    ui->lcdNumber_8->setDecMode();

    ui->label_test_mode->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    const QString pass_color_str("color: black;background-color: springgreen");
    ui->label_test_mode->setStyleSheet(pass_color_str);

    ui->label_test_mode_2->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_mode_3->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_mode_4->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_mode_5->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_mode_6->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_mode_7->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_mode_8->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_2->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_3->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_4->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_5->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_6->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_7->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
    ui->label_test_result_8->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));

    InitLcdDisplay();

#ifdef EN_GIF_DISPLAY
    movie_testing = new QMovie("gif2.gif");//:/images/gif2.gif
    movie_testing->setScaledSize(ui->label_pass_gif->size());
    movie_testing->start();
    ui->label_pass_gif->setMovie(movie_testing);
    movie_testing->stop();
#endif

//    movie_point = new QMovie("gif1.gif");//:/images/gif1.gif
//    movie_wifi = new QMovie("gif1.gif");//:/images/gif1.gif
//    movie_touch = new QMovie("gif1.gif");//:/images/gif1.gif
//    movie_time = new QMovie("gif1.gif");//:/images/gif1.gif
//    movie_rs485 = new QMovie("gif1.gif");//:/images/gif1.gif
//    movie_pump = new QMovie("gif1.gif");//:/images/gif1.gif

//    movie_point->setScaledSize(ui->label_point_state->size());
//    movie_wifi->setScaledSize(ui->label_wifi_state->size());
//    movie_touch->setScaledSize(ui->label_rs485_state->size());
//    movie_time->setScaledSize(ui->label_time_state->size());
//    movie_rs485->setScaledSize(ui->label_rs485_state->size());
//    movie_pump->setScaledSize(ui->label_pump_state->size());

    memset(result,0,sizeof(result));
    test_step = 0;

    com.len = 0;
    com.connect_flag  = false;
    com_err_cnt = 10;
    err_flag = false;
    modbus_thread = new QDemoThread(ModbusCommunication, this);
    modbus_thread->start();
    QObject::connect(this, &MainWindow::TestResultSignal,
                     this, &MainWindow::TestResultSlot);
    QObject::connect(this, &MainWindow::TestStepSignal,
                     this, &MainWindow::TestStepSlot);

//    QObject::connect(this, &MainWindow::SerialPortErrorDealSignal,
//                     this, &MainWindow::SerialPortErrorDealSlot);

    myTimer = new QTimer(this);
    connect(myTimer,&QTimer::timeout,this,&MainWindow::Timer_Task1);

//    if (myTimer->isActive() == false)
//    {
//       myTimer->start(200);
//#ifdef EN_DB_TIMER
//       qDebug("start timer\r\n");
//#endif
//    }
    #if (EN_LANGUAGE_ENGLISH == 1)
    QString str[][2] = {
      {tr("Machine model"), tr("")},
      {tr("OTA version"), tr("")},
      {tr("Control mode"), tr("")},
      {tr("Cell model"), tr("")},
      {tr("IC SN"), tr("")},
      {tr("Machine ID"), tr("")},
      //  {tr("FFFFFFFFFFFFFFFFFFFFFFFF"), tr("")},
      {tr("Modbus addr"), tr("")},
      {tr(""), tr("")},
    };
    #else
    QString str[][2] = {
      {tr("机器型号"), tr("")},
      {tr("软件版本"), tr("")},
      {tr("机器配置"), tr("")},
      {tr("电解片规格"), tr("")},
      {tr("芯片序列号"), tr("")},      
      {tr("设备ID"), tr("")},
      {tr("MODBUS地址"), tr("")},
      {tr(""), tr("")},
    };
    #endif
    QHBoxLayout *layout = new QHBoxLayout;
    p_table_widget = new QTableWidget(ui->textBrowser);
    p_table_widget->setColumnCount(2);
    int i = 0;
    while (str[i][0].length() > 0) {
        QTableWidgetItem *item0 = new QTableWidgetItem;
        QTableWidgetItem *item1 = new QTableWidgetItem;
        item0->setText(str[i][0]);
        item1->setText(str[i][1]);
        item0->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
        item1->setTextAlignment(Qt::AlignVCenter);
        p_table_widget->insertRow(i);
        p_table_widget->setItem(i, 0, item0);
        p_table_widget->setItem(i, 1, item1);
        i++;
    }
    p_table_widget->verticalHeader()->setHidden(true);
    p_table_widget->horizontalHeader()->setHidden(true);
    p_table_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    p_table_widget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    p_table_widget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //p_table_widget->horizontalHeader()->setResizeContentsPrecision(QHeaderView::Fixed);
    p_table_widget->setSelectionMode(QAbstractItemView::NoSelection);
    //p_table_widget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    int width = ui->textBrowser->width();//p_table_widget->width();

    p_table_widget->setColumnWidth(0, width / 3);
    p_table_widget->setColumnWidth(1, width / 3 * 2);

    p_table_widget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    p_table_widget->setFont(QFont(SYS_FONT_TYPE, 12));
    connect(p_table_widget, &QTableWidget::cellClicked, this, &MainWindow::table_widget_cell_clicked);
    layout->addWidget(p_table_widget);
    layout->setContentsMargins(0, 0, 0, 0);
    ui->textBrowser->setLayout(layout);

    ui->help_btn->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));

    dev_data.setting_modbus_addr = 0x08;
    dev_data.setting_cell_model = 20;
    dev_data.setting_control_mode = 0;
    TestResultShow(0);
#if (EN_LANGUAGE_ENGLISH == 1)
    ui->label_com->setText(tr("Com"));
    ui->label_temp1->setText(tr("3.W.Temp[26~35]℃"));
    ui->label_SIZE->setText(tr("14.Cell model"));
    ui->label_key->setText(tr("KEY"));
    ui->OpenSerialButton->setText(tr("Open"));
    ui->RefreshSerialButton->setText(tr("Refresh"));
    ui->label_size_select->setText(tr("Testing cell model:"));
    ui->label_key1->setText(tr("POWER\nLOCK"));
    ui->label_key5->setText(tr("SETING\nCALIB"));
    ui->label_buzzer->setText(tr("BUZZER"));
    ui->label_motor->setText(tr("ACID DOSING"));
    ui->label_POINT->setText(tr("8.Dry/Flow SW"));
    ui->label_rs485->setText(tr("10.RS485"));
    ui->label_TIME->setText(tr("11.RTC"));
    ui->help_btn->setText(tr("Help"));

#endif
}

void MainWindow::SetKeepSettingFlag(int flag)
{
    g_keep_setting_flag = flag;
}

void MainWindow::SetTestMode(int mode)
{
    QString str;

    test_mode = mode;
    #if (EN_LANGUAGE_ENGLISH == 1)
    if (test_mode == TEST_MODE_PCBA){
        ui->label_test_mode->setText(tr("PCBA mode"));
        ui->label_temp2->setText(tr("4.M.Temp[50~58]­℃"));
    } else if (test_mode == TEST_MODE_PRODUCT){
        ui->label_test_mode->setText(tr("Machine mode"));
        ui->label_temp2->setText(tr("4.M.Temp[12~80]­℃"));
    }
    #else
    if (test_mode == TEST_MODE_PCBA){
        ui->label_test_mode->setText(tr("PCBA测试"));
        ui->label_temp2->setText(tr("4.机箱温度[50~58]­℃"));
    } else if (test_mode == TEST_MODE_PRODUCT){
        ui->label_test_mode->setText(tr("整机测试"));
        ui->label_temp2->setText(tr("4.机箱温度[12~80]­℃"));
    }
    #endif
}

bool MainWindow::SetElectrolyzerIndex(int index)
{
    bool ret = false;
    QString str;

    if (index < 0) {
        return ret;
    }
    if (ui->comboBox->count()>0 &&
        index < ui->comboBox->count()) {
        ui->comboBox->setCurrentIndex(index);
        ui->comboBox->setEnabled(false);
        if (test_mode == TEST_MODE_PRODUCT) {
            str = QString("5.SJ[%1~%2]V")\
                  .arg(electrolytic_sj_range[index][0])\
                  .arg(electrolytic_sj_range[index][1]);
            // str.sprintf("5.SJ[%.1f~%.1f]V",
            //             electrolytic_sj_range[index][0],
            //             electrolytic_sj_range[index][1]);
            ui->label_sj->setText(str);
            str = QString("6.SI[%1~%2]A")\
                  .arg(electrolytic_si_range[index][0])\
                  .arg(electrolytic_si_range[index][1]);
            // str.sprintf("6.SI[%.1f~%.1f]A",
            //             electrolytic_si_range[index][0],
            //             electrolytic_si_range[index][1]);
            ui->label_si->setText(str);
            str = QString("7.SV[%1~%2]V")\
                  .arg(electrolytic_sv_range[index][0])\
                  .arg(electrolytic_sv_range[index][1]);
            // str.sprintf("7.SV[%.1f~%.1f]V",
            //             ,
            //             electrolytic_sv_range[index][1]);
            ui->label_sv->setText(str);
        }
        ret = true;
    }

    return ret;
}

MainWindow::~MainWindow()
{
    if (myTimer->isActive())
    {
       myTimer->stop();
    }
#if (EN_LANGUAGE_ENGLISH == 1)
    if(ui->OpenSerialButton->text()!=tr("Open")) {
#else
    if(ui->OpenSerialButton->text()!=tr("打开串口")) {
#endif
        on_OpenSerialButton_clicked();
    }
    delete myTimer;
    delete ui;
}

void MainWindow::on_RefreshSerialButton_clicked()
{
    //查找可用的串口
    InitSerialPortList();
}

void MainWindow::RetryOpenSerial(void)
{
    return;
    qDebug("RetryOpenSerial start");
    dev_mutex.lock();
    err_flag = true;
    dev_mutex.unlock();
    OsSleep(3000);
    //关闭串口
    com.connect_flag = false;
    test_step = 0;
    OsSleep(500);
    dev_mutex.lock();
    if (serial != nullptr) {
        qDebug("close serial start");

        serial->close();
        qDebug("close serial start1");
        QObject::disconnect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
        //qRegisterMetaType<QSerialPort::SerialPortError>("SerialThread");
        QObject::disconnect(serial, &QSerialPort::errorOccurred,
                         this, &MainWindow::SerialPortErrorOccurred);
        qDebug("close serial start2");
        //delete serial;
        //serial->deleteLater();
        OsSleep(500);
        //delete serial;
        serial = nullptr;
        qDebug("close serial end");
    }
    if (myTimer->isActive() == true)
    {
       myTimer->stop();
    }
    serial=new QSerialPort;
    //设置串口名
    serial->setPortName(ui->portBox->currentText());
    //打开串口
    if (!serial->open(QIODevice::ReadWrite)) {
#if (EN_LANGUAGE_ENGLISH == 1)
        QMessageBox::critical(this, tr("Error"), tr("Failed to open communication port!"));
#else
       QMessageBox::critical(this, tr("错误"), tr("串口设备打开失败，请检查!"));
#endif
       return ;
    }
    serial->setBaudRate(QSerialPort::Baud9600);
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    //设置流控制
    serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制
    serial->clearError();
    serial->flush();

    QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
    qRegisterMetaType<QSerialPort::SerialPortError>("SerialThread");
    QObject::connect(serial, &QSerialPort::errorOccurred,
                     this, &MainWindow::SerialPortErrorOccurred);

    com_err_cnt = 10;
    com.connect_flag = true;

    test_step = 0;
    if (myTimer->isActive() == false)
    {
       myTimer->start(200);
    }
    dev_mutex.unlock();

    dev_mutex.lock();
    err_flag = false;
    dev_mutex.unlock();
    qDebug("RetryOpenSerial end");
}

void MainWindow::on_OpenSerialButton_clicked()
{
    QString name;
    QFile sys_file(tr(SYS_INI_FILE));
    std::string str;

#if (EN_LANGUAGE_ENGLISH == 1)
    if(ui->OpenSerialButton->text()==tr("Open"))
#else
    if(ui->OpenSerialButton->text()==tr("打开串口"))
#endif
    {
        if(ui->portBox->currentText() == "")
        {
#if (EN_LANGUAGE_ENGLISH == 1)
            QMessageBox::critical(this, tr("Error"), tr("Failed to open communication port!"));
#else
            QMessageBox::critical(this, tr("错误"), tr("串口设备打开失败，请检查!"));
#endif
            return ;
        }
        else
        {
             serial=new QSerialPort;

             //设置串口名
             name = ui->portBox->currentText();
             serial->setPortName(name);
             //打开串口

             if (!serial->open(QIODevice::ReadWrite)) {
#if (EN_LANGUAGE_ENGLISH == 1)
            QMessageBox::critical(this, tr("Error"), tr("Failed to open communication port!"));
#else
            QMessageBox::critical(this, tr("错误"), tr("串口设备打开失败，请检查!"));
#endif
                return ;
             }
             serial->moveToThread(modbus_thread);

#if 1
             serial->setBaudRate(QSerialPort::Baud9600);
             serial->setDataBits(QSerialPort::Data8);
             serial->setParity(QSerialPort::NoParity);
             serial->setStopBits(QSerialPort::OneStop);
#else
             //设置波特率
             switch(ui->baudBox->currentIndex())
             {
                case 0:
                    serial->setBaudRate(QSerialPort::Baud1200);
                    break;
                case 1:
                    serial->setBaudRate(QSerialPort::Baud2400);
                    break;
                case 2:
                    serial->setBaudRate(QSerialPort::Baud4800);
                    break;
                case 3:
                    serial->setBaudRate(QSerialPort::Baud9600);
                    break;
                case 4:
                    serial->setBaudRate(QSerialPort::Baud19200);
                    break;
                case 5:
                    serial->setBaudRate(QSerialPort::Baud38400);
                    break;
                case 6:
                    serial->setBaudRate(QSerialPort::Baud57600);
                    break;
                case 7:
                    serial->setBaudRate(QSerialPort::Baud115200);
                    break;
                default:
                    break;
             }
             //设置数据为
             switch(ui->dataBox->currentIndex())
             {
                 case 0:
                    serial->setDataBits(QSerialPort::Data8);
                    break;
                 default:
                    break;
             }
             //设置校验位
             switch (ui->checkBox->currentIndex())
             {
                 case 0:
                    serial->setParity(QSerialPort::NoParity);
                    break;
                 default:
                    break;
             }
             //设置停止为
             switch(ui->stopBox->currentIndex())
             {
                 case 0:
                    serial->setStopBits(QSerialPort::OneStop);
                    break;
                 case 1:
                    serial->setStopBits(QSerialPort::TwoStop);
                    break;
                 default:
                    break;
             }
#endif
             //设置流控制
             serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制
             serial->clearError();
             serial->flush();

             //关闭设置菜单使能
             ui->portBox->setEnabled(false);
             ui->RefreshSerialButton->setEnabled(false);
#if 0
             ui->dataBox->setEnabled(false);
             ui->checkBox->setEnabled(false);
             ui->stopBox->setEnabled(false);
             ui->baudBox->setEnabled(false);
#endif
             ui->TestButton->setEnabled(true);
             ui->TestButton->setStyleSheet("color: rgb(134, 134, 134)");
             //ui->TestButton->setStyleSheet("background-color: rgb(240, 240, 240)");
             ui->TestButton->setStyleSheet("background-color: rgb(124, 179, 228)");
             #if (EN_LANGUAGE_ENGLISH == 1)
             ui->OpenSerialButton->setText(tr("Close"));
             #else
             ui->OpenSerialButton->setText(tr("关闭串口"));
             #endif

             QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
             qRegisterMetaType<QSerialPort::SerialPortError>("SerialThread");
             QObject::connect(serial, &QSerialPort::errorOccurred,
                              this, &MainWindow::SerialPortErrorOccurred);
             dev_mutex.lock();
             com_err_cnt = 10;
             com.connect_flag = true;

             test_step = 0;
             dev_mutex.unlock();
             ui->label_judge_time->hide();
             ui->label_soft_version->hide();
             ui->label_product_type->hide();
             // 写入串口记录文件
             if (sys_file.open(QIODevice::WriteOnly)) {
                 str = name.toStdString();
                 sys_file.write(str.c_str(), strlen(str.c_str()));
                 sys_file.flush();
                 sys_file.close();
             }

             InitTextBrowser();
             InitDevcieData();
             if (myTimer->isActive() == false)
             {
                myTimer->start(200);
             }
        }
    }
    else
    {
        //关闭串口
        com.connect_flag = false;
        test_step = 0;
        OsSleep(500);
        serial_mutex.lock();
        if (serial != nullptr) {

            serial->close();
            serial->deleteLater();
            serial = nullptr;
            qDebug("close serial");
        }
        serial_mutex.unlock();

        //恢复使能
        ui->portBox->setEnabled(true);
        ui->RefreshSerialButton->setEnabled(true);
#if 0
        ui->baudBox->setEnabled(true);
        ui->dataBox->setEnabled(true);
        ui->checkBox->setEnabled(true);
        ui->stopBox->setEnabled(true);
#endif
        ui->TestButton->setEnabled(false);
        ui->TestButton->setStyleSheet("color: rgb(134, 134, 134)");
        ui->TestButton->setStyleSheet("background-color: rgb(204, 204, 204)");
        #if (EN_LANGUAGE_ENGLISH == 1)
        ui->OpenSerialButton->setText(tr("Open"));
        #else
        ui->OpenSerialButton->setText(tr("打开串口"));
        #endif
        ui->label_judge_time->hide();
        ui->label_soft_version->hide();
        ui->label_product_type->hide();
        InitTextBrowser();
        InitDevcieData();
        dev_data.info_flag = 0;
        dev_data.test_result = 0;
        InfoDisplay();
        TestResultShow(0);

        if (myTimer->isActive() == true)
        {
           myTimer->stop();
        }
    }
}

void MainWindow::on_SendSerialButton_clicked()
{
#if 0
    if(ui->txtWrite->toPlainText().toLatin1() != " " &&
       ui->OpenSerialButton->text()==tr("关闭串口"))
            serial->write(ui->txtWrite->toPlainText().toLatin1());
    else
    {
        dialog = new QDialog(this);
        dialog->setModal(true);
        dialog->setToolTip("haha");
        //dialog->set;
        dialog->show();

    }
#endif
}

void MainWindow::on_ClearTxButton_clicked()
{
    //ui->txtWrite->setPlainText("");
}

void MainWindow::on_ClearRxButton_clicked()
{
    //ui->txtRead->setPlainText("");
}

void MainWindow::on_TestButton_clicked()
{
    test_step = 0;
    uint8_t b_buf[256];
    uint16_t buf[256];

    memset(result,0,sizeof(result));
    if(ui->TestButton->text()==tr("START"))
    {
        ui->TestButton->setText("STOP");
        ui->TestButton->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
//        ui->TestButton->setStyleSheet("color: rgb(255, 255, 255)");
//        ui->TestButton->setStyleSheet("background-color: red");
        ui->TestButton->adjustSize();
        ui->portBox->setEnabled(false);
        ui->comboBox->setEnabled(false);
        ui->OpenSerialButton->setEnabled(false);
        test_step = 1;
//        judge_time = 60000;
//        JudgeTimeDisplay();
//        ui->label_judge_time->show();
//        if (TestPrepare()) {
            InitDevcieData();
            if (myTimer->isActive() == false)
            {
               myTimer->start(200);
            }
//        }
        return ;
#if 0
        ui->dataBox->setEnabled(false);
        ui->checkBox->setEnabled(false);
        ui->stopBox->setEnabled(false);
        ui->baudBox->setEnabled(false);
#endif

#ifdef EN_GIF_DISPLAY
        movie_testing->start();
#endif

        com.connect_flag = false;
        memset(&result[7],1,6);
        memset(dev_data.touch,0,5);
        ui->OpenSerialButton->setEnabled(false);
        //ui->SendSerialButton->setEnabled(false);
        //ui->TestTypeBox->setEnabled(false);

        /*
        if (myTimer->isActive() == false)
        {
           myTimer->start(200);
           qDebug("start timer\r\n");
        }
        */

        ui->textBrowser->setText("测试步骤：\r\n"
                                 "a.请将打印工具接入电脑USB口\r\n"
                                 "b.选择端口号\r\n"
                                 "c.点击'打开串口'\r\n"
                                 "d.选择电解片规格\r\n"
                                 );

        clear_lcd_display();
    }
    else
    {
        ui->TestButton->setText("START");
        ui->TestButton->setFont(QFont(SYS_FONT_TYPE, FONT_SIZE_18));
//        ui->TestButton->setStyleSheet("color: rgb(255, 255, 255)");
//        ui->TestButton->setStyleSheet("background-color: rgb(124, 179, 228)");
        ui->TestButton->adjustSize();
//        ui->portBox->setEnabled(true);
//        ui->comboBox->setEnabled(true);
        ui->OpenSerialButton->setEnabled(true);
        test_step = 0;
        ui->label_judge_time->hide();

        if (myTimer->isActive())
        {
           myTimer->stop();
        }
        return ;
#if 0
        ui->dataBox->setEnabled(true);
        ui->checkBox->setEnabled(true);
        ui->stopBox->setEnabled(true);
        ui->baudBox->setEnabled(true);
#endif

#ifdef EN_GIF_DISPLAY
        movie_testing->stop();
#endif

        ui->OpenSerialButton->setEnabled(true);
        //ui->SendSerialButton->setEnabled(true);
        //ui->TestTypeBox->setEnabled(true);

        //myTimer->stop();
        //test_step = 0;
    }
}

void MainWindow::InitDevcieData(void)
{

//    QString Version;    // 软件版本
//    float PH;           // PH值
//    int ORP;            // ORP值
//    float temp1;        // 水温
//    float temp2;        // 机箱温度
//    float SJ;           // SJ值
//    float SI;           // SI值
//    float SV;           // SV值
//    bool point;         // 干接点/水流开关
//    bool wifi;          // WIFI状态
//    bool time;          // 时钟芯片状态
//    bool touch[5];      // 按键状态
//    bool rs485;
//    bool pump;
//    int size;           // 电解片规格
      dev_data.dev_id = 1;  // 默认设备id
      dev_data.version.clear();
      dev_data.ph = 0.0f;
      dev_data.orp = 0;
      dev_data.waterTemp = 0.0f;
      dev_data.bodyTemp = 0.0f;
      dev_data.temp1_err = 0;
      dev_data.temp1_int = 0;
      dev_data.temp2_err = 0;
      dev_data.temp2_int = 0;
      dev_data.sj = 0.0f;
      dev_data.si = 0.0f;
      dev_data.sv = 0.0f;
      dev_data.point = false;
      dev_data.wifi = false;
      dev_data.time = false;
      memset(dev_data.touch, 0, sizeof(dev_data.touch));
      dev_data.rs485 = false;
      dev_data.pump = false;
      dev_data.size = 0;
      dev_data.rc = false;
      dev_data.sr = false;
      dev_data.buzzer = false;
      dev_data.motor = false;
      dev_data.info_flag = 0;
      dev_data.test_result = 0;
      KeyDisplay();
      InitLcdDisplay();
      ui->label_point_state->setStyleSheet("background-color: white");
      ui->label_wifi_state->setStyleSheet("background-color: white");
      ui->label_rs485_state->setStyleSheet("background-color: white");
      ui->label_time_state->setStyleSheet("background-color: white");
      ui->label_sr_state->setStyleSheet("background-color: white");
      ui->label_rc_state->setStyleSheet("background-color: white");
      ui->label_key->setStyleSheet("background-color: white");
      ui->label_buzzer->setStyleSheet("background-color: white");
      ui->label_motor->setStyleSheet("background-color: white");
      dev_mutex.lock();
      if (dev_data.wifi) {
          ui->label_wifi_state->setText("ON");
      } else {
          ui->label_wifi_state->setText("OFF");
      }

      if (dev_data.point) {
          ui->label_point_state->setText("ON");
      } else {
          ui->label_point_state->setText("OFF");
      }

      if (dev_data.time) {
          ui->label_time_state->setText("ON");
      } else {
          ui->label_time_state->setText("OFF");
      }

      if (dev_data.rs485) {
          ui->label_rs485_state->setText("ON");
      } else {
          ui->label_rs485_state->setText("OFF");
      }

      if (dev_data.rc) {
          ui->label_rc_state->setText("ON");
      } else {
          ui->label_rc_state->setText("OFF");
      }

      if (dev_data.sr) {
          ui->label_sr_state->setText("ON");
      } else {
          ui->label_sr_state->setText("OFF");
      }
      dev_mutex.unlock();
      //ui->label_led->setStyleSheet("background-color: white");
}

void MainWindow::InitSerialPortList(void)
{
    //查找可用的串口
    QList <QString> name;
    QString old_name;
    QFile sys_file(tr(SYS_INI_FILE));
    std::string str;
    QByteArray buf;
    int index;

    old_name = ui->portBox->currentText();
    ui->portBox->clear();
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) {
        QSerialPort serial;
        serial.setPort(info);
        qDebug()<<serial.portName();
        name.push_back(serial.portName());
    }
    // qSort(name.begin(), name.end());
    for (int i = 0; i < name.count(); i++) {
        ui->portBox->addItem(name[i]);        
    }
    if (ui->portBox->count() > 0) {
        index = ui->portBox->findText(old_name);
        if (index < 0) {
            index = 0;
            ui->portBox->setCurrentIndex(index);
        }
        old_name = ui->portBox->itemText(index);
        if (!sys_file.open(QIODevice::ReadOnly)) {
            if (sys_file.open(QIODevice::WriteOnly)) {
                str = old_name.toStdString();
                sys_file.write(str.c_str(), strlen(str.c_str()));
                sys_file.flush();
                sys_file.close();
            }
        } else {    // 用配置文件读取
            buf = sys_file.readAll();
            old_name = QString(buf);
            index = ui->portBox->findText(old_name);
            if (index < 0) {
                index = 0;

            }
            ui->portBox->setCurrentIndex(index);
            qDebug()<<old_name<<" "<<index;
        }
    }
}

//int MainWindow::
int GetSerialPortErr(void)
{
    int ret = 0;

    serial_mutex.lock();
    if (serial != nullptr) {        
        ret = serial->error();        
    }
    serial_mutex.unlock();
    if (ret == QSerialPort::NoError) {
        ret = 0;
    } else {
        //qDebug("GetSerialPortErr:%d", ret);
        //if (ret == 10) {
        //serial->clearError();
        //emit TestResultSignal(R_FLAG_SERIAL_ERR);
        //}
    }
    //ret = 0;
    return ret;
}

//void MainWindow::
void ClearSerialPortRecvBuf(void)
{
    com.recv_buf.clear();
    serial_mutex.lock();
    if (serial != nullptr) {
        serial->clear();
    }
    serial_mutex.unlock();
}

//QByteArray &MainWindow::
QByteArray GetSerialPortRecvBuf(void)
{
    return com.recv_buf;
}

void MainWindow::SerialPortErrorOccurred(QSerialPort::SerialPortError error)
{
    qDebug("SerialPortErrorOccurred err occured:%d", error);
    //serial->clearError();
    //emit TestResultSignal(R_FLAG_SERIAL_ERR);
    RetryOpenSerial();
    return ;
    if(ui->TestButton->text()!=tr("START")) {
        on_TestButton_clicked();
    }
    OsSleep(500);
    //serial->clearError();
#if (EN_LANGUAGE_ENGLISH == 1)
    if(ui->OpenSerialButton->text()!=tr("Open")) {
#else
    if(ui->OpenSerialButton->text()!=tr("打开串口")) {
#endif
        on_OpenSerialButton_clicked();
    }

    //QMessageBox::critical(this, tr("错误"), tr("串口设备异常，请检查!"));
    InitSerialPortList();
    //emit SerialPortErrorDealSignal(error);
}

void MainWindow::TestStepSlot(int flag)
{
    if (flag == 0) {
        InitDevcieData();
    } else if (flag == 1) {
        judge_time = 60000;
        ui->label_judge_time->show();
        //ui->label_soft_version->show();
        //ui->label_product_type->show();
        ui->textBrowser->append("连接成功，开始检测！");
        //ui->textBrowser->append("软件版本：1.5.90");
        ui->textBrowser->append("请依次按下按键！");
        if (myTimer->isActive() == false) {
           myTimer->start(200);
        }
    } else if (flag == 2) {
        ui->textBrowser->append("连接成功，开始检测！");
        //ui->textBrowser->append("MCU ID:XXXXXXXXXX\r\n软件版本：1.5.90");
        ui->textBrowser->append("请依次按下按键！");
        //test_step++;
    }
}

void MainWindow::TestResultSlot(int flag)
{
    const QString pass_color_str("color: black;background-color: springgreen");
    const QString fail_color_str("color: black;background-color: red");
//    TestStepCtrl();
    if (flag == R_FLAG_SERIAL_CONNECT_ERR) {
        qDebug()<<"R_FLAG_SERIAL_CONNECT_ERR";
        if (myTimer->isActive()) {
           myTimer->stop();
        }
        ui->label_judge_time->hide();
        ui->label_soft_version->hide();
        ui->label_product_type->hide();
        InitTextBrowser();
        InitDevcieData();
        InitSerialPortList();
        dev_data.info_flag = 0;
        InfoDisplay();
        TestResultShow(0);
#if (EN_LANGUAGE_ENGLISH == 1)
        if(ui->OpenSerialButton->text()!=tr("Open")) {
#else
        if(ui->OpenSerialButton->text()!=tr("打开串口")) {
#endif
            on_OpenSerialButton_clicked();
        }
        //QMessageBox::critical(this, tr("错误"), tr("串口设备异常，请检查!"));
    }else if (flag == R_FLAG_SERIAL_ERR) {
        qDebug()<<"R_FLAG_SERIAL_ERR";
        if(ui->TestButton->text()!=tr("START")) {
            on_TestButton_clicked();
        }
        OsSleep(500);
#if (EN_LANGUAGE_ENGLISH == 1)
        if(ui->OpenSerialButton->text()!=tr("Open")) {
#else
        if(ui->OpenSerialButton->text()!=tr("打开串口")) {
#endif
            on_OpenSerialButton_clicked();
        }
#if (EN_LANGUAGE_ENGLISH == 1)
        QMessageBox::critical(this, tr("Error"), tr("Com error!"));
#else
        QMessageBox::critical(this, tr("错误"), tr("串口设备异常，请检查!"));
#endif
        InitSerialPortList();
    } else if (flag == R_FLAG_RS485_ERR) {
        //QMessageBox::critical(this, tr("错误"), tr("RS485通信错误，请检查!"));
        if (myTimer->isActive()) {
           myTimer->stop();
        }
        ui->label_judge_time->hide();
        ui->label_soft_version->hide();
        ui->label_product_type->hide();
        InitTextBrowser();
        InitDevcieData();
        dev_data.info_flag = 0;
        InfoDisplay();
        TestResultShow(0);
        //on_TestButton_clicked();
    } else if (flag == R_FLAG_TEST_PASS) {
        dev_data.test_result = 1;
//        if (myTimer->isActive()) {
//           myTimer->stop();
//        }
//        test_step++;
//        ManualConfirmationDlg dlg(this);
//        dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);
//        dlg.exec();

//        dev_data.buzzer = dlg.GetBuzzer();
//        dev_data.motor = dlg.GetMotor();
//        dev_data.led = dlg.GetLed();

//        if (!dev_data.buzzer || !dev_data.buzzer || !dev_data.buzzer) {
//            emit TestResultSignal(R_FLAG_TEST_FAIL);
//            return ;
//        }

        ui->textBrowser->clear();
        //ui->textBrowser->setStyleSheet("background-color: springgreen");
        //ui->textBrowser->append("\r\n\r\n\r\n\r\n\r\n");
        ui->textBrowser->append("<font size =\"5\" color=\"black\">""\r\n\测试通过\r\nPASS !!!""</font> ");
        TestDataResultDisplay();
        TestResultShow(1);

//        if (dev_data.buzzer) {
//            ui->label_buzzer->setStyleSheet(pass_color_str);
//        } else {
//            ui->label_buzzer->setStyleSheet(fail_color_str);
//        }
//        if (dev_data.motor) {
//            ui->label_motor->setStyleSheet(pass_color_str);
//        } else {
//            ui->label_motor->setStyleSheet(fail_color_str);
//        }
//        if (dev_data.led) {
//            ui->label_led->setStyleSheet(pass_color_str);
//        } else {
//            ui->label_led->setStyleSheet(fail_color_str);
//        }
//        on_TestButton_clicked();
    } else if (flag == R_FLAG_TEST_FAIL) {
        dev_data.test_result = 2;
//        if (myTimer->isActive()) {
//           myTimer->stop();
//        }
//        test_step++;
        ui->textBrowser->clear();
        //ui->textBrowser->setStyleSheet("background-color: red");
        //ui->textBrowser->append("\r\n\r\n\r\n\r\n\r\n");
        ui->textBrowser->append("<font size =\"6\" color=\"black\">""\r\n\测试失败\r\nFAIL !!!""</font> ");

        TestDataResultDisplay();
        TestResultShow(2);

//        on_TestButton_clicked();
    } else if (flag == R_FLAG_TEST_TIME_OUT) {
        dev_data.test_result = 3;
//        if (myTimer->isActive()) {
//           myTimer->stop();
//        }
//        test_step++;
        ui->textBrowser->clear();
        //ui->textBrowser->setStyleSheet("background-color: red");
        //ui->textBrowser->append("\r\n\r\n\r\n");
        ui->textBrowser->append("<font size =\"6\" color=\"black\">""\r\n\r\n    测试超时\r\n  请重新测试 !!!""</font> ");
        TestDataResultDisplay();
        TestResultShow(2);
//        on_TestButton_clicked();
    }
}

void MainWindow::SerialPortErrorDealSlot(QSerialPort::SerialPortError error)
{
    qDebug("SerialPortErrorDealSlot err occured:%d", error);
    if(ui->TestButton->text()!=tr("START")) {
        on_TestButton_clicked();
    }
    OsSleep(500);
#if (EN_LANGUAGE_ENGLISH == 1)
    if(ui->OpenSerialButton->text()!=tr("Open")) {
#else
    if(ui->OpenSerialButton->text()!=tr("打开串口")) {
#endif
        on_OpenSerialButton_clicked();  
    }
    //serial->clearError();
#if (EN_LANGUAGE_ENGLISH == 1)
    QMessageBox::critical(this, tr("Error"), tr("Com error!"));
#else
    QMessageBox::critical(this, tr("错误"), tr("串口设备异常，请检查!"));
#endif
    InitSerialPortList();

}

//读取接收到的消息
void MainWindow::ReadData()
{
    /*
    A 1
    A 1
    PH 4
    ORP 4
    TEMP1 4
    TEMP2 4
    SJ 4
    SI 4
    SV 4
    POINT 1
    WIFI 1
    TOUCH 1
    TIME 1
    RS485 1
    PUMP 1
    SIZE 4

    ALL 40
    */
    QString data;
    QByteArray buf;
    int n;

    buf = serial->readAll();
    //qDebug()<<"1>"<<ByteArrayToHexString(buf);
    //qDebug()<<"1>"<<buf;
    com.recv_buf.append(buf);
    //qDebug()<<"1>"<<ByteArrayToHexString(com.recv_buf);
    //qDebug()<<"2>"<<com.recv_buf;
    //qDebug()<<"3>"<<com.recv_buf.size();

    //while(serial->waitForReadyRead(20))
    //qApp->processEvents();
    //buf.append(buf_temp.toHex().toUpper());
    n = com.recv_buf.size();
//    for (int i = 0; i < n; i++) {
//        qDebug("d[%d]:%02x %02x", i, com.recv_buf[i]&0xFF, buf[i]&0xFF);
//    }
    return ;
#if 0
    buf.clear();
    if(com.recv_buf.size() >= 45)
    {
        const char temp1 = com.recv_buf[0];
        const char temp2 = com.recv_buf[1];
        if(temp1 == 0x41 && temp2 == 0x41)
        {
            com.connect_flag = true;
            //qDebug()<<"4>"<<"right protocl";
            data = com.recv_buf;
            //qDebug()<<"5>"data.size();
            //int xx  = Com.recv_buf[2]<<24 | Com.recv_buf[3]<<16 | Com.recv_buf[4]<<8 | Com.recv_buf[5];
            //qDebug()<<"xx:"<<(float)xx;
            dev_data.ph = com.recv_buf[2]<<24 | com.recv_buf[3]<<16 | com.recv_buf[4]<<8 | com.recv_buf[5];
            dev_data.orp = com.recv_buf[6]<<24 | com.recv_buf[7]<<16 | com.recv_buf[8]<<8 | com.recv_buf[9];
            dev_data.temp1 = com.recv_buf[10]<<24 | com.recv_buf[11]<<16 | com.recv_buf[12]<<8 | com.recv_buf[13];
            dev_data.temp2 = com.recv_buf[14]<<24 | com.recv_buf[15]<<16 | com.recv_buf[16]<<8 | com.recv_buf[17];
            dev_data.sj = com.recv_buf[18]<<24 | com.recv_buf[19]<<16 | com.recv_buf[20]<<8 | com.recv_buf[21];
            dev_data.si = com.recv_buf[22]<<24 | com.recv_buf[23]<<16 | com.recv_buf[24]<<8 | com.recv_buf[25];
            dev_data.sv = com.recv_buf[26]<<24 | com.recv_buf[27]<<16 | com.recv_buf[28]<<8 | com.recv_buf[29];
            dev_data.point = com.recv_buf[30];
            dev_data.wifi = com.recv_buf[31];
            dev_data.time = com.recv_buf[32];
            //Para.touch = Com.recv_buf[33];
            dev_data.rs485 = com.recv_buf[34];
            dev_data.pump = com.recv_buf[35];
            dev_data.size = com.recv_buf[36]<<24 | com.recv_buf[37]<<16 | com.recv_buf[38]<<8 | com.recv_buf[39];
            dev_data.touch[0] = com.recv_buf[40];
            dev_data.touch[1] = com.recv_buf[41];
            dev_data.touch[2] = com.recv_buf[42];
            dev_data.touch[3] = com.recv_buf[43];
            dev_data.touch[4] = com.recv_buf[44];
            //qDebug()<<"5>"<<"PH:"<<Para.PH;
            qDebug("5>touch:%d%d%d%d%d",dev_data.touch[0],dev_data.touch[1],dev_data.touch[2],dev_data.touch[3],dev_data.touch[4]);
            lcd_display();
        }
        else
        {
            com.connect_flag = false;
            qDebug()<<"4>"<<"error protocl";
        }
        com.recv_buf.clear();
    }
#endif
}

void MainWindow::GetDeviceData(void)
{
    int32_t ret;
    uint8_t b_buf[256] = {0};
    uint16_t r_buf[256] = {0};
    int32_t index;
    float min[3], max[3];
    int err;

//    dev_mutex.lock();
//    if (err_flag) {
//        dev_mutex.unlock();
//        return;
//    }
//    dev_mutex.unlock();

    //ret = ModbusReadInputBits(0x00, 0x6, b_buf);
    if (com.connect_flag) { // 已经连接串口
        err = GetSerialPortErr();
        if (err == QSerialPort::ResourceError) {
            serial->close();
            if (!serial->open(QIODevice::ReadWrite)) {
               //if (com.com_state == QSerialPort::NoError) {
                    emit TestResultSignal(R_FLAG_SERIAL_CONNECT_ERR);
                //}
               //QMessageBox::critical(this, tr("错误"), tr("串口设备打开失败，请检查!"));
               return ;
            }
        } else if(err != QSerialPort::NoError) {
            //serial->clearError();
            serial->close();
            if (!serial->open(QIODevice::ReadWrite)) {
               //if (com.com_state == QSerialPort::NoError) {
                    emit TestResultSignal(R_FLAG_SERIAL_CONNECT_ERR);
                //}
               //QMessageBox::critical(this, tr("错误"), tr("串口设备打开失败，请检查!"));
               return ;
            }
        }
        com.com_state = GetSerialPortErr();
OsSleep(10);
        ret = ModbusReadRegisters(0x01, 0x01, r_buf);
        if (ret == 0x01) {
            dev_data.dev_id = r_buf[0];
        }
OsSleep(10);
        ret = ModbusReadRegisters(0x00, 0x02, r_buf);
        //ret = 0x02;
        if (ret == 0x02) {
            //dev_data.dev_id = r_buf[1];
            if (r_buf[0] != 0x03) {
                ret = ModbusWriteRegister(0x0000, 3);    // 进入工厂测试模式
                //ret = 0x01;
                if (ret == 0x01) {

                }
            }
            if (test_step == 0) {
                qDebug("test_step1++");
                test_step++;
            }
            if (com_err_cnt >= 2) {
                qDebug("TestStepSignal(1)");
                emit TestStepSignal(1);
                qDebug("TestStepSignal(1) end");
            }
            dev_mutex.lock();
            com_err_cnt = 0;
            dev_mutex.unlock();
        } else {
            if (com_err_cnt < 10) {
                dev_mutex.lock();
                com_err_cnt++;
                dev_mutex.unlock();
            }
        }
    }
    if (com_err_cnt == 2) {
        test_step = 0;

        qDebug("TestResultSignal(R_FLAG_RS485_ERR)");
        emit TestResultSignal(R_FLAG_RS485_ERR);
        com_err_cnt++;
        //serial->clear();
        //serial->clearError();
        //emit TestStepSignal(1);
        return ;
    }

//    if ((test_step == 2) && (GetSerialPortErr() == 0)) {//(test_step) > 0 && (test_step < 2)) {
//    qDebug("GetDeviceData:%d", test_step);
    if ((test_step == 1) && com.connect_flag && (GetSerialPortErr() == 0)) {//(test_step) > 0 && (test_step < 2)) {
//        qDebug("GetDeviceData");
//        ret = ModbusReadRegisters(0x00, 0x01, r_buf);
//        if (ret == 0x01) {
//            dev_data.mode = r_buf[0];
//            qDebug("mode:%d", dev_data.mode);
//        }
        if ((dev_data.soft_ver_i >= 0x000A002A) &&
            (dev_data.product_type == PRODUCT_TYPE_M)) {// 10.0.40之后

            if (dev_data.setting_flag == 1) {
                r_buf[0] = dev_data.setting_modbus_addr;
                r_buf[1] = dev_data.setting_control_mode;
                r_buf[2] = dev_data.setting_cell_model;
                OsSleep(10);
                ret = ModbusWriteFactoryRegisters(0x00, 0x03, r_buf);
                qDebug("ModbusWriteFactoryRegisters:%d %d", dev_data.setting_flag, ret);
                if (ret == 0x03) {
                    dev_data.setting_flag = 2;
                }
            }
            OsSleep(10);
            ret = ModbusReadFactoryRegisters(0x00, 0x0B, r_buf);
            if (ret == 0x0B) {
                dev_data.modbus_addr = r_buf[0];
                dev_data.control_mode = r_buf[1];
                dev_data.cell_model = r_buf[2];
                dev_data.ic_id[2] = ((uint32_t)(r_buf[3]) << 16) | r_buf[4];
                dev_data.ic_id[1] = ((uint32_t)(r_buf[5]) << 16) | r_buf[6];
                dev_data.ic_id[0] = ((uint32_t)(r_buf[7]) << 16) | r_buf[8];
                dev_data.ic_id[3] = ((uint32_t)(r_buf[9]) << 16) | r_buf[10];
                dev_data.info_flag = 1;
            }
            //qDebug("cell:%d %d %d %d", g_keep_setting_flag, dev_data.modbus_addr, dev_data.control_mode, dev_data.cell_model);
            if ((g_keep_setting_flag) && ((dev_data.modbus_addr != dev_data.setting_modbus_addr) ||
                (dev_data.control_mode != dev_data.setting_control_mode) ||
                (dev_data.cell_model != dev_data.setting_cell_model))) {
                OsSleep(10);
                r_buf[0] = dev_data.setting_modbus_addr;
                r_buf[1] = dev_data.setting_control_mode;
                r_buf[2] = dev_data.setting_cell_model;
                OsSleep(10);
                ret = ModbusWriteFactoryRegisters(0x00, 0x03, r_buf);
                qDebug("ModbusWriteFactoryRegisters:%d %d", dev_data.setting_flag, ret);
                if (ret == 0x03) {
                    //dev_data.setting_flag = 2;
                }
                OsSleep(10);
                ret = ModbusReadFactoryRegisters(0x00, 0x0B, r_buf);
                if (ret == 0x0B) {
                    dev_data.modbus_addr = r_buf[0];
                    dev_data.control_mode = r_buf[1];
                    dev_data.cell_model = r_buf[2];
                    dev_data.ic_id[2] = ((uint32_t)(r_buf[3]) << 16) | r_buf[4];
                    dev_data.ic_id[1] = ((uint32_t)(r_buf[5]) << 16) | r_buf[6];
                    dev_data.ic_id[0] = ((uint32_t)(r_buf[7]) << 16) | r_buf[8];
                    dev_data.ic_id[3] = ((uint32_t)(r_buf[9]) << 16) | r_buf[10];
                    dev_data.info_flag = 1;
                }
            }
        }
        OsSleep(10);
        ret = ModbusReadInputRegisters(0x00, 0x10, r_buf);
        if (ret == 0x10) {
            dev_mutex.lock();
            dev_data.orp = (short)r_buf[0];
            dev_data.ph = r_buf[1] / 100.0;
            //dev_data.temp1 = r_buf[3] / 10.0;//水温暂时写死
            // L款PCBA测试台架没有接水温温度传感器，暂时写死
            if (test_mode == TEST_MODE_PCBA) {
                if ((r_buf[3] == 250) &&
                    (dev_data.product_type == PRODUCT_TYPE_L)) {
                    dev_data.waterTemp = r_buf[3] / 10.0;//水温暂时写死
                    dev_data.waterTemp += 1.5;
                } else {
                    //dev_data.temp1 = 0;
                    if (r_buf[3] != 250){
                        dev_data.temp1_err = 0;
                        dev_data.waterTemp = r_buf[3] / 10.0;
                    } else {
                        dev_data.temp1_err++;
                        if (dev_data.temp1_err > 10){
                            dev_data.waterTemp = 0.0;
                        }
                    }
                }
            } else {
                if (r_buf[3] != 250){
                    dev_data.temp1_err = 0;
                    dev_data.waterTemp = r_buf[3] / 10.0;
                } else {
                    dev_data.temp1_err++;
                    if (dev_data.temp1_err > 10){
                        dev_data.waterTemp = 0.0;
                    }
                }
            }
            dev_data.temp1_int = r_buf[3];
            //dev_data.temp2 = r_buf[4] / 10.0;
            if (test_mode == TEST_MODE_PCBA) {
                //dev_data.temp1 = 0;
                if (r_buf[4] != 250){
                    dev_data.temp2_err = 0;
                    dev_data.bodyTemp = r_buf[4] / 10.0;
                } else {
                    dev_data.temp2_err++;
                    if (dev_data.temp2_err > 10){
                        dev_data.bodyTemp = 0.0;
                    }
                }
            } else {
                if (r_buf[4] != 250){
                    dev_data.temp2_err = 0;
                    dev_data.bodyTemp = r_buf[4] / 10.0;
                } else {
                    dev_data.temp2_err++;
                    if (dev_data.temp2_err > 10){
                        dev_data.bodyTemp = 0.0;
                    }
                }
            }
            dev_data.temp2_int = r_buf[4];
            if (test_mode == TEST_MODE_PCBA) {
                switch (r_buf[7]) {
                case 9: dev_data.size = ELECTROLYTIC_STRIP_1; break;
                case 10: dev_data.size = ELECTROLYTIC_STRIP_1; break;
                case 13: dev_data.size = ELECTROLYTIC_STRIP_1; break;
                case 16: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                case 20: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                case 17: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                case 30: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                case 21: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                case 40: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                case 25: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                case 26: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                }
            } else {
                if (dev_data.product_type == PRODUCT_TYPE_L) {  // L款
                    switch (r_buf[7]) {
                    case 9: dev_data.size = ELECTROLYTIC_STRIP_2; break;
                    case 10: dev_data.size = ELECTROLYTIC_STRIP_2; break;
                    case 16: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                    case 20: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                    case 21: dev_data.size = ELECTROLYTIC_STRIP_6; break;
                    case 30: dev_data.size = ELECTROLYTIC_STRIP_6; break;
                    case 26: dev_data.size = ELECTROLYTIC_STRIP_7; break;
                    case 40: dev_data.size = ELECTROLYTIC_STRIP_7; break;
                    default: dev_data.size = 0;
                    }
                } else if (dev_data.product_type == PRODUCT_TYPE_M) {  // M款
                    switch (r_buf[7]) {
                    case 9: dev_data.size = ELECTROLYTIC_STRIP_1; break;
                    case 10: dev_data.size = ELECTROLYTIC_STRIP_1; break;
                    case 16: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                    case 20: dev_data.size = ELECTROLYTIC_STRIP_3; break;
                    case 21: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                    case 30: dev_data.size = ELECTROLYTIC_STRIP_4; break;
                    case 26: dev_data.size = ELECTROLYTIC_STRIP_5; break;
                    case 40: dev_data.size = ELECTROLYTIC_STRIP_5; break;
                    default: dev_data.size = 0;
                    }
                }
            }
//            switch (r_buf[7]) {
//            case 9: dev_data.size = ELECTROLYTIC_STRIP_1; break;
//            case 10: dev_data.size = ELECTROLYTIC_STRIP_1; break;
//            case 13: dev_data.size = ELECTROLYTIC_STRIP_1; break;
//            case 16: dev_data.size = ELECTROLYTIC_STRIP_2; break;
//            case 20: dev_data.size = ELECTROLYTIC_STRIP_2; break;
//            case 17: dev_data.size = ELECTROLYTIC_STRIP_2; break;
//            case 30: dev_data.size = ELECTROLYTIC_STRIP_3; break;
//            case 21: dev_data.size = ELECTROLYTIC_STRIP_3; break;
//            case 40: dev_data.size = ELECTROLYTIC_STRIP_4; break;
//            case 25: dev_data.size = ELECTROLYTIC_STRIP_4; break;
//            case 26: dev_data.size = ELECTROLYTIC_STRIP_4; break;
//            }

            //dev_data.size = r_buf[7];
            dev_data.sj = r_buf[8] / 1000.0;
//            dev_data.si = r_buf[9] / 10.0;
//            dev_data.sv = r_buf[10] / 10.0;
            dev_data.si = r_buf[11] / 100.0;            
            if (test_mode == TEST_MODE_PCBA) {
                if (r_buf[12] / 100.0 > 24.0) {
                    dev_data.sv = 23.5;
                } else {
                   dev_data.sv = r_buf[12] / 100.0;
                }
            } else {
                dev_data.sv = r_buf[12] / 100.0;
            }
            // 软件版本组织
            snprintf(dev_data.soft_ver, sizeof(dev_data.soft_ver),
                     "%d.%d.%d", r_buf[13], r_buf[14] >> 0x08, r_buf[14] & 0xFF);
            dev_data.soft_ver_i = (((uint32_t)r_buf[13]) << 16) | r_buf[14];
            // 产品类型组织
            dev_data.product_type = r_buf[15];
            dev_mutex.unlock();
        }
OsSleep(10);
        ret = ModbusReadInputBits(0x00, 0x10, b_buf);
OsSleep(10);
        ret = ModbusReadInputBits(0x30, 0x10, b_buf);
OsSleep(10);
        ret = ModbusReadInputBits(0x60, 0x10, b_buf);
        if (ret == 0x10) {
            dev_mutex.lock();
            if (!dev_data.touch[0] && b_buf[0]) {    // 记录有按下的状态
                dev_data.touch[0] = true;
            }

            if (!dev_data.touch[1] && b_buf[1]) {    // 记录有按下的状态
                dev_data.touch[1] = true;
            }

            if (!dev_data.touch[2] && b_buf[2]) {    // 记录有按下的状态
                dev_data.touch[2] = true;
            }

            if (!dev_data.touch[3] && b_buf[3]) {    // 记录有按下的状态
                dev_data.touch[3] = true;
            }

            if (!dev_data.touch[4] && b_buf[4]) {    // 记录有按下的状态
                dev_data.touch[4] = true;
            }

            // 记录干接点和水流开关检测锁定
            if (judge_time < 58000) {   // 避免误触发防抖

                if (b_buf[5]){
                    dev_data.point_ok_cnt++;
                    dev_data.point_fail_cnt = 0;
                } else {
                    dev_data.point_ok_cnt = 0;
                    dev_data.point_fail_cnt++;
                }
                if (dev_data.point_ok_cnt >= 2)
                {
                    dev_data.point = true;
                }
                else if(dev_data.point_fail_cnt >= 2)
                {
                    dev_data.point = false;
                }
               // if ((dev_data.point == 0) && b_buf[5]) {
               //     dev_data.point = b_buf[5];
               // }
            }
            dev_data.wifi = b_buf[6];
            dev_data.time = b_buf[7];

            if (test_mode == TEST_MODE_PCBA) {
                if (dev_data.si < 1.8 || dev_data.si > 10.2) {
                    dev_data.sr = false;
                    dev_data.rc = false;
                } else {
                    dev_data.sr = true;
                    dev_data.rc = true;
                }
            } else {
                //dev_data.sr = b_buf[8];
                //dev_data.rc = b_buf[9];
                index = ui->comboBox->currentIndex();
                min[0] = electrolytic_si_range[index][0];
                max[0] = electrolytic_si_range[index][1];
                min[1] = electrolytic_sj_range[index][0];
                max[1] = electrolytic_sj_range[index][1];
                min[2] = electrolytic_sv_range[index][0];
                max[2] = electrolytic_sv_range[index][1];
                if(((dev_data.si >= min[0]) && (dev_data.si <= max[0])) &&
                   ((dev_data.sj >= min[1]) && (dev_data.sj <= max[1])) &&
                   ((dev_data.sv >= min[2]) && (dev_data.sv <= max[2]))) {
                    if (judge_time < 38000) {   // 约22秒后避免误触发防抖
                        dev_data.sr = true;
                        dev_data.rc = true;
                    }
                } else {
                    dev_data.sr = false;
                    dev_data.rc = false;
                }
            }

            dev_data.rs485 = true;  // 连接上了，测试通过
            if (b_buf[11]){
                dev_data.motor_ok_cnt++;
            } else {
                dev_data.motor_ok_cnt = 0;
            }

            if (dev_data.motor_ok_cnt >=2) {
                if (!dev_data.motor) {      // 锁存
                    dev_data.motor = true;//b_buf[11];
                }
            }

            if (b_buf[12]){
                dev_data.buzzer_ok_cnt++;
            } else {
                dev_data.buzzer_ok_cnt = 0;
            }

            if (dev_data.buzzer_ok_cnt >= 2) {
                if (!dev_data.buzzer) {     // 锁存
                    dev_data.buzzer = true;//b_buf[12];
                }
            }


            if (test_mode == TEST_MODE_PRODUCT) {
                //整机测试以水流开关信号作为蜂鸣器和电机功能有效性确认信号
                dev_data.buzzer = dev_data.point;
                dev_data.motor = dev_data.point;
            }
            dev_mutex.unlock();
        }
    }
}

//int MainWindow::
int SendData(void *buf, int len)
{
    int ret = 0;
    assert(buf);
    serial_mutex.lock();
    if ((serial != nullptr) && com.connect_flag) {
        ret = (int)serial->write((const char *)buf, len);
        serial->flush();
        //qDebug("send data");
    }
    serial_mutex.unlock();

    return ret;
}

//结果判定
void MainWindow::result_judge()
{
    bool rs = false;
#if 0
    for(int i = 0;i<14;i++)
    {
        rs = false;

        switch(i)
        {
        case 0:
            if(dev_data.ph >= 7.0f && dev_data.ph <= 7.1f)
                rs = true;
            else
                rs = false;
            break;
        case 1:
            if(dev_data.orp >= 700 && dev_data.orp <= 701)
                rs = true;
            else
                rs = false;
            break;
        case 2:
            if(dev_data.temp1 >= 25.0f && dev_data.temp1 <= 25.5f)
                rs = true;
            else
                rs = false;
            break;
        case 3:
            if(dev_data.temp2 >= 25.0f && dev_data.temp2 <= 25.5f)
                rs = true;
            else
                rs = false;
            break;
        case 4:
            if(dev_data.sj >= 25.0f && dev_data.sj <= 25.5f)
                rs = true;
            else
                rs = false;
            break;
        case 5:
            if(dev_data.si >= 25.0f && dev_data.si <= 25.5f)
                rs = true;
            else
                rs = false;
            break;
        case 6:
            if(dev_data.sv >= 25.0f && dev_data.sv <= 25.5f)
                rs = true;
            else
                rs = false;
            break;
        case 7:
            if(dev_data.point)
                rs = true;
            else
                rs = false;
            break;
        case 8:
            if(dev_data.wifi)
                rs = true;
            else
                rs = false;
            break;
        case 9:
            if(dev_data.time)
                rs = true;
            else
                rs = false;
            break;
        case 10:
            if(dev_data.touch[0] == 1 &&
               dev_data.touch[1] == 1 &&
               dev_data.touch[2] == 1 &&
               dev_data.touch[3] == 1 &&
               dev_data.touch[4] == 1)
                rs = true;
            else
                rs = false;
            break;
        case 11:
            if(dev_data.rs485)
                rs = true;
            else
                rs = false;
            break;
        case 12:
            if(dev_data.pump)
                rs = true;
            else
                rs = false;
            break;
        case 13:
            if((dev_data.size == 9 && ui->comboBox->currentIndex() == 0) ||
               (dev_data.size == 16 && ui->comboBox->currentIndex() == 1) ||
               (dev_data.size == 21 && ui->comboBox->currentIndex() == 2) ||
               (dev_data.size == 26 && ui->comboBox->currentIndex() == 3))
                rs = true;
            else
                rs = false;
            break;
        default:
            break;
        }

        if(result[i] < 2)
        {
            if(rs == true)
            {
                if(i == 10)
                    result[i] = 2;
                else
                {
                    if(cnt_p[i] < JUDGE_PASS_NUM)
                        cnt_p[i]++;
                    else
                    {
                        result[i] = 2;
                    }
                    cnt_f[i] = 0;
                }
            }
            else
            {
                if(i != 10)
                {
                    cnt_p[i] = 0;
                    if(cnt_f[i] < JUDGE_FAIL_NUM)
                        cnt_f[i]++;
                    else
                    {
                        result[i] = 3;
                    }
                }
            }
        }
    }
#endif

#if 1
    qDebug("test_step:%d rs:%d%d%d%d%d%d%d% d%d%d%d%d%d%d\r\n",
           test_step,
           result[0],
           result[1],
           result[2],
           result[3],
           result[4],
           result[5],
           result[6],
           result[7],
           result[8],
           result[9],
           result[10],
           result[11],
           result[12],
           result[13]);
#endif
}

//结果显示
void MainWindow::result_display()
{
#if 0
    if(result[0] == 2)
    {
        ui->lcdNumber_4->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""PH PASS""</font> ");
        result[0] = 4;
    }
    else if(result[0] == 3)
    {
        ui->lcdNumber_4->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""PH检测超时！""</font> ");
        result[0] = 5;
    }
    else if(result[0] < 2)
    {
        ui->lcdNumber_4->setStyleSheet("color: black;background-color: white");
    }

    if(result[1] == 2)
    {
        ui->lcdNumber_3->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""ORP PASS""</font> ");
        result[1] = 4;
    }
    else if(result[1] == 3)
    {
        ui->lcdNumber_3->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""ORP检测超时！""</font> ");
        result[1] = 5;
    }
    else if(result[1] < 2)
    {
        ui->lcdNumber_3->setStyleSheet("color: black;background-color: white");
    }

    if(result[2] == 2)
    {
        ui->lcdNumber_2->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""水温 PASS""</font> ");
        result[2] = 4;
    }
    else if(result[2] == 3)
    {
        ui->lcdNumber_2->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""水温检测超时！""</font> ");
        result[2] = 5;
    }
    else if(result[2] < 2)
    {
        ui->lcdNumber_2->setStyleSheet("color: black;background-color: white");
    }

    if(result[3] == 2)
    {
        ui->lcdNumber->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""机箱温度 PASS""</font> ");
        result[3] = 4;
    }
    else if(result[3] == 3)
    {
        ui->lcdNumber->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""机箱温度检测超时！""</font> ");
        result[3] = 5;
    }
    else if(result[3] < 2)
    {
        ui->lcdNumber->setStyleSheet("color: black;background-color: white");
    }

    if(result[4] == 2)
    {
        ui->lcdNumber_5->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""SJ PASS""</font> ");
        result[4] = 4;
    }
    else if(result[4] == 3)
    {
        ui->lcdNumber_5->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""SJ检测超时！""</font> ");
        result[4] = 5;
    }
    else if(result[4] < 2)
    {
        ui->lcdNumber_5->setStyleSheet("color: black;background-color: white");
    }

    if(result[5] == 2)
    {
        ui->lcdNumber_6->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""SI PASS""</font> ");
        result[5] = 4;
    }
    else if(result[5] == 3)
    {
        ui->lcdNumber_6->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""SI检测超时！""</font> ");
        result[5] = 5;
    }
    else if(result[5] < 2)
    {
        ui->lcdNumber_6->setStyleSheet("color: black;background-color: white");
    }

    if(result[6] == 2)
    {
        ui->lcdNumber_7->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""SV PASS""</font> ");
        result[6] = 4;
    }
    else if(result[6] == 3)
    {
        ui->lcdNumber_7->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""SV检测超时！""</font> ");
        result[6] = 5;
    }
    else if(result[6] < 2)
    {
        ui->lcdNumber_7->setStyleSheet("color: black;background-color: white");
    }

    if(result[7] == 0)
    {
        movie_point->stop();
        ui->label_point_rs->clear();
        ui->label_point_rs->setText("");
    }
    else if(result[7] == 1)
    {
        movie_point->start();
        ui->label_point_rs->setMovie(movie_point);
    }
    else if(result[7] == 2)
    {
        movie_point->stop();
        ui->label_point_rs->setText("PASS");
        ui->label_point_rs->setFont(QFont("方正舒体", 16));
        ui->label_point_rs->setStyleSheet("color: rgb(58, 203, 77)");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""干接点 PASS""</font> ");
        result[7] = 4;
    }
    else if(result[7] == 3)
    {
        movie_point->stop();
        ui->label_point_rs->setText("FAIL");
        ui->label_point_rs->setFont(QFont("方正舒体", 16));
        ui->label_point_rs->setStyleSheet("color: red");
        ui->textBrowser->append("<font color=red>""干接点检测超时！""</font> ");
        result[7] = 5;
    }

    if(result[8] == 0)
    {
        movie_wifi->stop();
        ui->label_wifi_rs->clear();
        ui->label_wifi_rs->setText("");
    }
    else if(result[8] == 1)
    {
        movie_wifi->start();
        ui->label_wifi_rs->setMovie(movie_wifi);
    }
    else if(result[8] == 2)
    {
        movie_wifi->stop();
        ui->label_wifi_rs->setText("PASS");
        ui->label_wifi_rs->setFont(QFont("方正舒体", 16));
        ui->label_wifi_rs->setStyleSheet("color: rgb(58, 203, 77)");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""WIFI PASS""</font> ");
        result[8] = 4;
    }
    else if(result[8] == 3)
    {
        movie_wifi->stop();
        ui->label_wifi_rs->setText("FAIL");
        ui->label_wifi_rs->setFont(QFont("方正舒体", 16));
        ui->label_wifi_rs->setStyleSheet("color: red");
        ui->textBrowser->append("<font color=red>""WIFI检测超时！""</font> ");
        result[8] = 5;
    }

    if(result[9] == 0)
    {
        movie_time->stop();
        ui->label_time_rs->clear();
        ui->label_time_rs->setText("");
    }
    else if(result[9] == 1)
    {
        movie_time->start();
        ui->label_time_rs->setMovie(movie_time);
    }
    else if(result[9] == 2)
    {
        movie_time->stop();
        ui->label_time_rs->setText("PASS");
        ui->label_time_rs->setFont(QFont("方正舒体", 16));
        ui->label_time_rs->setStyleSheet("color: rgb(58, 203, 77)");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""时钟芯片 PASS""</font> ");
        result[9] = 4;
    }
    else if(result[9] == 3)
    {
        movie_time->stop();
        ui->label_time_rs->setText("FAIL");
        ui->label_time_rs->setFont(QFont("方正舒体", 16));
        ui->label_time_rs->setStyleSheet("color: red");
        ui->textBrowser->append("<font color=red>""时钟芯片检测超时！""</font> ");
        result[9] = 5;
    }

    if(result[10] == 0)
    {
        movie_touch->stop();
        ui->label_touch_rs->clear();
        ui->label_touch_rs->setText("");
        ui->label_key1->setStyleSheet("color: black;background-color: white");
        ui->label_key2->setStyleSheet("color: black;background-color: white");
        ui->label_key3->setStyleSheet("color: black;background-color: white");
        ui->label_key4->setStyleSheet("color: black;background-color: white");
        ui->label_key5->setStyleSheet("color: black;background-color: white");
    }
    else if(result[10] == 1)
    {
        movie_touch->start();
        ui->label_touch_rs->setMovie(movie_touch);
        if(dev_data.touch[0])
            ui->label_key1->setStyleSheet("color: white;background-color: rgb(58, 203, 77)");
        if(dev_data.touch[1])
            ui->label_key2->setStyleSheet("color: white;background-color: rgb(58, 203, 77)");
        if(dev_data.touch[2])
            ui->label_key3->setStyleSheet("color: white;background-color: rgb(58, 203, 77)");
        if(dev_data.touch[3])
            ui->label_key4->setStyleSheet("color: white;background-color: rgb(58, 203, 77)");
        if(dev_data.touch[4])
            ui->label_key5->setStyleSheet("color: white;background-color: rgb(58, 203, 77)");
    }
    else if(result[10] == 2)
    {
        movie_touch->stop();
        ui->label_touch_rs->setText("PASS");
        ui->label_touch_rs->setFont(QFont("方正舒体", 16));
        ui->label_touch_rs->setStyleSheet("color: rgb(58, 203, 77)");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""触摸芯片 PASS""</font> ");
        result[10] = 4;
    }
    else if(result[10] == 3)
    {
        movie_touch->stop();
        ui->label_touch_state->setText("FAIL");
        ui->label_touch_state->setFont(QFont("方正舒体", 16));
        ui->label_touch_state->setStyleSheet("color: red");
        ui->textBrowser->append("<font color=red>""触摸芯片检测超时！""</font> ");
        result[10] = 5;
    }

    if(result[11] == 0)
    {
        movie_rs485->stop();
        ui->label_rs485_state->clear();
        ui->label_rs485_state->setText("");
    }
    else if(result[11] == 1)
    {
        movie_rs485->start();
        ui->label_rs485_state->setMovie(movie_rs485);
    }
    else if(result[11] == 2)
    {
        movie_rs485->stop();
        ui->label_rs485_state->setText("PASS");
        ui->label_rs485_state->setFont(QFont("方正舒体", 16));
        ui->label_rs485_state->setStyleSheet("color: rgb(58, 203, 77)");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""RS485 PASS""</font> ");
        result[11] = 4;
    }
    else if(result[11] == 3)
    {
        movie_rs485->stop();
        ui->label_rs485_rs->setText("FAIL");
        ui->label_rs485_rs->setFont(QFont("方正舒体", 16));
        ui->label_rs485_rs->setStyleSheet("color: red");
        ui->textBrowser->append("<font color=red>""RS485检测超时！""</font> ");
        result[11] = 5;
    }

    if(result[12] == 0)
    {
        movie_pump->stop();
        ui->label_pump_rs->clear();
        ui->label_pump_rs->setText("");
    }
    else if(result[12] == 1)
    {
        movie_pump->start();
        ui->label_pump_rs->setMovie(movie_pump);
    }
    else if(result[12] == 2)
    {
        movie_pump->stop();
        ui->label_pump_rs->setText("PASS");
        ui->label_pump_rs->setFont(QFont("方正舒体", 16));
        ui->label_pump_rs->setStyleSheet("color: rgb(58, 203, 77)");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""药泵 PASS""</font> ");
        result[12] = 4;
    }
    else if(result[12] == 3)
    {
        movie_pump->stop();
        ui->label_pump_rs->setText("FAIL");
        ui->label_pump_rs->setFont(QFont("方正舒体", 16));
        ui->label_pump_rs->setStyleSheet("color: red");
        ui->textBrowser->append("<font color=red>""药泵检测超时""</font> ");
        result[12] = 5;
    }

    if(result[13] == 2)
    {
        ui->lcdNumber_8->setStyleSheet("color: rgb(58, 203, 77);background-color: white");
        //ui->textBrowser->append("<font color=\"#3ACB4D\">""电解片规格 PASS""</font> ");
        result[13] = 4;
    }
    else if(result[13] == 3)
    {
        ui->lcdNumber_8->setStyleSheet("color: red;background-color: white");
        ui->textBrowser->append("<font color=red>""电解片规格检测超时！""</font> ");
        result[13] = 5;
    }
    else if(result[13] < 2)
    {
        ui->lcdNumber_8->setStyleSheet("color: black;background-color: white");
    }
#endif
}

bool MainWindow::CheckSerialPortReady(const QString &port_name)
{
    bool flag = false;
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) {
        QSerialPort serial;
        serial.setPort(info);
        if (serial.portName() == port_name) {
            flag = true;
        }
    }
    return flag;
}

//定时器任务
void MainWindow::Timer_Task1()
{
    uint8_t bits_buf[512] = {0};
    uint16_t regs_buf[512] = {0};
    uint16_t err;

//    qDebug("Timer_Task1");
//    ModbusReadInputBits(0x0000, 16, bits_buf);
//    ModbusReadInputBits(0x0060, 8, bits_buf);
//    ModbusReadInputRegisters(0x0000, 16, regs_buf);
//    test_step_ctrl();
//    TestStepCtrl();
    UpdateDataDisplay();
//    err = serial->error();//GetSerialPortErr();
//    if (err == 10) {
//        serial->clearError();
//        qDebug("serial err:%d", err);
//    }

    return ;
    //find_com_loop();
    test_step_ctrl();
//    com_send_heartbeat();
}

//轮询监测端口
void MainWindow::find_com_loop()
{
    QString str;
    //QString str2 = QString::number(ui->StepTextEdit->blockCount(), 10);
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);
        if(serial.portName() != "")
        {
#ifdef EN_DB_COM
            qDebug() << "has com\r\n";
#endif
            for(int8_t n = 0;n<ui->portBox->count();n++)
            {
                //if(ui->portBox->itemText() != serial.portName())
                    //ui->portBox->addItem(serial.portName());
            }
            //qDebug() << ui->portBox->count();
            if(ui->portBox->currentText() != serial.portName())
                ui->portBox->addItem(serial.portName());
        }
        else
        {
            #ifdef EN_DB_COM
            qDebug() << "no com\r\n";
            #endif
        }
    }

}

//下发心跳包
void MainWindow::com_send_heartbeat()
{
    /*
    A 1
    A 1
    PH 4
    ORP 4
    TEMP1 4
    TEMP2 4
    SJ 4
    SI 4
    SV 4
    POINT 1
    WIFI 1
    TOUCH 1
    TIME 1
    RS485 1
    PUMP 1
    SIZE 4

    ALL 40
    */
    if(ui->TestButton->text()==tr("START"))
    {
        test_step = 0;
    }
    else if(ui->TestButton->text()==tr("STOP"))
    {
#if 1
        com.send_buf[0] = 0x41;
        com.send_buf[1] = 0x41;
        com.send_buf[2] = 0xFF;//40 E6 66 66
        com.send_buf[3] = 0xFF;
        com.send_buf[4] = 0xFF;
        com.send_buf[5] = 0xFF;
        com.send_buf[6] = 0x40;//40 E6 66 66
        com.send_buf[7] = 0xE6;
        com.send_buf[8] = 0x66;
        com.send_buf[9] = 0x66;
        com.send_buf[10] = 0x00;//40 E6 66 66
        com.send_buf[11] = 0x00;
        com.send_buf[12] = 0x00;
        com.send_buf[13] = 0x19;
        com.send_buf[14] = 0xFF;//40 E6 66 66
        com.send_buf[15] = 0xFF;
        com.send_buf[16] = 0xFF;
        com.send_buf[17] = 0xFB;
        com.send_buf[18] = 0x40;//40 E6 66 66
        com.send_buf[19] = 0xE6;
        com.send_buf[20] = 0x66;
        com.send_buf[21] = 0x66;
        com.send_buf[22] = 0x40;//40 E6 66 66
        com.send_buf[23] = 0xE6;
        com.send_buf[24] = 0x66;
        com.send_buf[25] = 0x66;
        com.send_buf[26] = 0x40;//40 E6 66 66
        com.send_buf[27] = 0xE6;
        com.send_buf[28] = 0x66;
        com.send_buf[29] = 0x66;
        com.send_buf[30] = 0x01;//1 1 1 1 1 1
        com.send_buf[31] = 0x01;
        com.send_buf[32] = 0x00;
        com.send_buf[33] = 0x00;
        com.send_buf[34] = 0x00;
        com.send_buf[35] = 0x01;
        com.send_buf[36] = 0x00;//40 E6 66 66
        com.send_buf[37] = 0x00;
        com.send_buf[38] = 0x00;
        com.send_buf[39] = 0x14;
        com.send_buf[40] = 0x00;//key1
        com.send_buf[41] = 0x00;//key2
        com.send_buf[42] = 0x01;//key3
        com.send_buf[43] = 0x01;//key4
        com.send_buf[44] = 0x01;//key5
        serial->write(com.send_buf);
#else
        serial->write("AA11112222333344445555666677771111118888");
#endif
    }
}

bool MainWindow::TestPrepare(void)
{
    bool ret = false;
    int len = 0;
    uint16_t r_buf[10];

    InitTextBrowser();
    InitDevcieData();
    return true;

    test_step = 0;
    if(test_step == 0) {
        ui->textBrowser->append("连接中...");
        if(com.connect_flag) {
            len = ModbusReadRegisters(0x01, 0x01, r_buf);
            if (len == 0x01) {
                dev_data.dev_id = r_buf[0];
                qDebug("dev_id:%d", dev_data.dev_id);
                len = ModbusWriteRegister(0x0000, 3);    // 进入工厂测试模式
                if (len == 0x01) {
                    ui->textBrowser->append("连接成功，开始检测！");
                    //ui->textBrowser->append("MCU ID:XXXXXXXXXX\r\n软件版本：1.5.90");
                    ui->textBrowser->append("请依次按下按键！");
                    test_step++;
                    ret = true;
                    return ret;
                }
            }
        }
        emit TestResultSignal(R_FLAG_RS485_ERR);
    }

    return ret;
}

void MainWindow::TestStepCtrl(void)
{
    int ret;
    uint16_t r_buf[128];
    float min, max;
//    static int flag = 0;
//    if (flag == 0 && test_step > 0) {
//        ManualConfirmationDlg dlg;
//        dlg.exec();
//        flag = 1;
//    }
    bool test_result = true;

    dev_mutex.lock();
    if (err_flag) {
        dev_mutex.unlock();
        return;
    }
    dev_mutex.unlock();

    if (0) {//test_step == 1 && com.connect_flag) {
#if 0
        ret = ModbusReadRegisters(0x01, 0x01, r_buf);
        if (ret == 0x01) {
            dev_data.dev_id = r_buf[0];
            qDebug("dev_id:%d", dev_data.dev_id);
            ret = ModbusWriteRegister(0x0000, 3);    // 进入工厂测试模式
            if (ret == 0x01) {
                emit TestStepSignal(2);
//                test_step++;
//                ret = true;
//                return ret;
            }
        }
//        judge_time = 60000;
//        JudgeTimeDisplay();
        //ui->label_judge_time->show();
//        if (TestPrepare()) {
//            if (myTimer->isActive() == false)
//            {
//               myTimer->start(200);
//            }
//        }
#endif
    } else if (test_step == 1) {

        if ((dev_data.touch[0] == true) &&
            (dev_data.touch[1] == true) &&
            (dev_data.touch[2] == true) &&
            (dev_data.touch[3] == true) &&
            (dev_data.touch[4] == true)) {

            if (((dev_data.ph < 4.0) || (dev_data.ph > 6.5)) && m_phEnable)
            {
                test_result = false;
            }

            if (((dev_data.orp < 615) || (dev_data.orp > 718)) && m_orpEnable)
            {
                test_result = false;
            }


            if (((dev_data.waterTemp < 26.0) || (dev_data.waterTemp > 35.0)) && m_waterTempEanble)
            {
                test_result = false;
            }

            if (test_mode == TEST_MODE_PCBA) {
                if ((dev_data.bodyTemp < 50.0)||(dev_data.bodyTemp > 58.0)){
                    test_result = false;
                }
            } else {
                if ((dev_data.bodyTemp < 12.0) || (dev_data.bodyTemp > 80.0)) {
                    test_result = false;
                }
            }

            if (test_mode == TEST_MODE_PRODUCT) {
                min = electrolytic_sj_range[ui->comboBox->currentIndex()][0];
                max = electrolytic_sj_range[ui->comboBox->currentIndex()][1];
            } else {
                min = 0.4;
                max = 3.3;
            }

            if ((dev_data.sj < min) || (dev_data.sj > max)) {
                test_result = false;
            }

            if (test_mode == TEST_MODE_PRODUCT) {
                min = electrolytic_si_range[ui->comboBox->currentIndex()][0];
                max = electrolytic_si_range[ui->comboBox->currentIndex()][1];
            } else {
                min = 1.8;
                max = 10.2;
            }

            if ((dev_data.si < min) || (dev_data.si > max)) {
                test_result = false;
            }

            if (test_mode == TEST_MODE_PRODUCT) {
                min = electrolytic_sv_range[ui->comboBox->currentIndex()][0];
                max = electrolytic_sv_range[ui->comboBox->currentIndex()][1];
            } else {
                min = 10.0;
                max = 24.0;
            }

            if ((dev_data.sv < min) || (dev_data.sv > max)) {
                test_result = false;
            }

            if (!dev_data.point) {
                test_result = false;
            }

            if (!dev_data.wifi) {
                test_result = false;
            }

            if (!dev_data.rs485) {
                test_result = false;
            }

            if (!dev_data.time) {
                test_result = false;
            }

            if (!dev_data.sr) {
                test_result = false;
            }

            if (!dev_data.rc) {
                test_result = false;
            }

            if (!dev_data.buzzer) {
                test_result = false;
            }

            if (!dev_data.motor) {
                test_result = false;
            }
            if (((ui->comboBox->currentIndex() == 0) && (dev_data.size != ELECTROLYTIC_STRIP_1)) ||
                ((ui->comboBox->currentIndex() == 1) && (dev_data.size != ELECTROLYTIC_STRIP_2)) ||
                ((ui->comboBox->currentIndex() == 2) && (dev_data.size != ELECTROLYTIC_STRIP_3)) ||
                ((ui->comboBox->currentIndex() == 3) && (dev_data.size != ELECTROLYTIC_STRIP_4)) ||
                ((ui->comboBox->currentIndex() == 4) && (dev_data.size != ELECTROLYTIC_STRIP_5)) ||
                ((ui->comboBox->currentIndex() == 5) && (dev_data.size != ELECTROLYTIC_STRIP_6)) ||
                ((ui->comboBox->currentIndex() == 6) && (dev_data.size != ELECTROLYTIC_STRIP_7))) {
                test_result = false;
            }
//            if (((ui->comboBox->currentIndex() == 0) && (dev_data.size != 9)) ||
//                ((ui->comboBox->currentIndex() == 1) && (dev_data.size != 16)) ||
//                ((ui->comboBox->currentIndex() == 2) && (dev_data.size != 21)) ||
//                ((ui->comboBox->currentIndex() == 3) && (dev_data.size != 26))) {
//                test_result = false;
//            }

            if (test_result) {
                //test_step++;
                OsSleep(300);
                if (judge_time < 58000) {
                    emit TestResultSignal(R_FLAG_TEST_PASS);
                }
            } else {
                if (judge_time < 30000) {   // 剩余不超过30秒
                    //test_step++;
                    OsSleep(300);
                    emit TestResultSignal(R_FLAG_TEST_FAIL);
                }
            }
        } else {
            if (judge_time == 0) {
                //test_step++;
                OsSleep(300);
                emit TestResultSignal(R_FLAG_TEST_TIME_OUT);
            }
        }

    }
}

//测试流程控制
void MainWindow::test_step_ctrl()
{
    if(test_step == 1) {
        if (judge_time == 0) {
            test_step++;
        }
    }
    else if(test_step == 2)
    {
        test_step++;
        //ui->textBrowser->append("<font size =\"16\" color=\"#3ACB4D\">""\r\n\r\n测试通过!!!""</font> ");
    }
    else if(test_step == 3)
    {

        ui->textBrowser->append("<font size =\"6\" color=\"red\">""\r\n\r\n请检查电路板并重新测试 !!!""</font> ");
        //test_step++;

        on_TestButton_clicked();
        //emit TestResultSignal();
    }
    return ;
    if(ui->TestButton->text()!=tr("STOP"))
    {
        test_step = 0;

        memset(result,0,sizeof(result));
        memset(cnt_p,0,sizeof(cnt_p));
        memset(cnt_f,0,sizeof(cnt_f));
        return;
    }

    if(test_step == 0)
    {
        ui->textBrowser->append("连接中...");
//        ret = ModbusReadRegisters(0x01, 0x01, r_buf);
//        if (ret == 0x01) {
//           //dev_data.dev_id = r_buf[0];
//           qDebug("dev_id:%d", dev_data.dev_id);

//        }
        test_step++;
    }
    else if(test_step == 1)
    {
        if(com.connect_flag == true)
        {
            ui->textBrowser->append("连接成功\r\n开始检测");
            test_step++;
        }
    }
    else if(test_step == 2)
    {
        //ui->textBrowser->append("MCU ID:XXXXXXXXXX\r\n软件版本：1.5.90");
        ui->textBrowser->append("请依次按下按键！");
        test_step++;
    }
    else if(test_step == 3)
    {
//        result_judge();
//        result_display();
//        if(result[0] == 5 ||
//            result[1] ==  5 ||
//            result[2] ==  5 ||
//            result[3] ==  5 ||
//            result[4] ==  5 ||
//            result[5] ==  5 ||
//            result[6] ==  5 ||
//            result[7] ==  5 ||
//            result[8] ==  5 ||
//            result[9] ==  5 ||
//            result[11] ==  5 ||
//            result[12] ==  5 ||
//            result[13] ==  5)
//        {
//            test_step = 5;
//        }

//        for(int i = 0;i<14;i++)
//        {
//            if(result[i] != 2)
//                return;
//        }
        if (judge_time == 0) {
            test_step++;
        }
    }
    else if(test_step == 4)
    {
        test_step++;
        //ui->textBrowser->append("<font size =\"16\" color=\"#3ACB4D\">""\r\n\r\n测试通过 !!!""</font> ");
    }
    else if(test_step == 5)
    {

        ui->textBrowser->append("<font size =\"5\" color=\"red\">""\r\n\r\n请检查电路板并重新测试 !!!""</font> ");
        //test_step++;
        on_TestButton_clicked();
    }
}

void MainWindow::JudgeTimeDisplay(void)
{
    QString str;
    #if (EN_LANGUAGE_ENGLISH == 1)
    str.sprintf("Times:%02d S", judge_time / 1000);
    #else
    str = QString("倒计时:%1秒").arg(judge_time / 1000,2);
    // str.sprintf("倒计时:%02d秒", judge_time / 1000);
    #endif
    ui->label_judge_time->setText(str);
}

void MainWindow::SoftVersionDisplay(void)
{
    QString str;
    str = QString("OTA版本:     %1").arg(dev_data.soft_ver);
    // str.sprintf("OTA版本:     %s", dev_data.soft_ver);
    ui->label_soft_version->setText(str);
}

void MainWindow::ProductTypeDisplay(void)
{
    QString str;

    switch(dev_data.product_type) {
    case PRODUCT_TYPE_L:
        str = QString("产品类型:     盐氯机L款");
        // str.sprintf("产品类型:     盐氯机L款");
        break;
    case PRODUCT_TYPE_M:
        if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0B) {
            str = QString("产品类型:     盐氯机M款(1500ppm低盐提示定制)");
        } else if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0C) {
            str = QString("产品类型:     盐氯机M款(新版APP)");
        }else if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0D) {
            str = QString("产品类型:     盐氯机M款(空气开关定制)");
        }  else if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0E) {
            str = QString("产品类型:     盐氯机M款(匈牙利定制)");
        } else {
            str = QString("产品类型:     盐氯机M款");
        }
        break;
    default:
        break;
    }

    ui->label_product_type->setText(str);
}

void MainWindow::InfoDisplay(void)
{
    dev_mutex.lock();
    if ((test_step > 0) && com.connect_flag) {
        QString str;
        QTableWidgetItem *item;

        item = p_table_widget->item(0, 1);
        switch(dev_data.product_type) {
        case PRODUCT_TYPE_L:
#if (EN_LANGUAGE_ENGLISH == 1)
            str.sprintf("Mr.Pure");
#else
            str = QString("盐氯机L款");
            // str.sprintf("盐氯机L款");
#endif
            break;
        case PRODUCT_TYPE_M:
            if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0B) {
#if (EN_LANGUAGE_ENGLISH == 1)
            str.sprintf("InverClear(1500ppm Low-salt)");
#else
            str = QString("盐氯机M款(1500ppm低盐提示定制)");
            // str.sprintf("盐氯机M款(1500ppm低盐提示定制)");
#endif
            } else if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0D ||
                       ((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0E) {
#if (EN_LANGUAGE_ENGLISH == 1)
            str.sprintf("InverClear(GAS_SW)");
#else
            str = QString("盐氯机M款(空气开关定制)");
            // str.sprintf("盐氯机M款(空气开关定制)");
#endif
            } else if (((dev_data.soft_ver_i >> 16) & 0xFF) == 0x0C) {
#if (EN_LANGUAGE_ENGLISH == 1)
            str.sprintf("InverClear(NEW APP)");
#else
            str = QString("盐氯机M款(新版APP)");
            // str.sprintf("盐氯机M款(新版APP)");
#endif
            } else {
#if (EN_LANGUAGE_ENGLISH == 1)
            str.sprintf("InverClear");
#else
            str = QString("盐氯机M款");
            // str.sprintf("盐氯机M款");
#endif
            }
            break;
        default:
            break;
        }
        item->setText(str);

        item = p_table_widget->item(1, 1);
        str = QString("%1").arg(dev_data.soft_ver);
        // str.sprintf("%s", dev_data.soft_ver);
        item->setText(str);

        if (dev_data.info_flag == 1) {
            item = p_table_widget->item(2, 1);
            switch (dev_data.control_mode) {
            case 0: str = tr("F1 (Inverter + Manual)"); break;
            case 1: str = tr("F2 (Auto pH + Manual)"); break;
            case 2: str = tr("F3 (Smart + Manual)"); break;
            case 3: str = tr("F4 (Manual)"); break;
            default: str = tr(""); break;
            }
            item->setText(str);

            item = p_table_widget->item(3, 1);
            switch (dev_data.cell_model) {
            case 10: str = tr("10g"); break;
            case 20: str = tr("16g"); break;
            case 30: str = tr("22g"); break;
            case 40: str = tr("28g"); break;
            default: str = tr(""); break;
            }
            item->setText(str);

            item = p_table_widget->item(4, 1);
            str = QString("%1%2%3").arg(dev_data.ic_id[2],8,16,QChar('0')).toUpper()
                  .arg(dev_data.ic_id[1],8,16,QChar('0')).toUpper()
                  .arg(dev_data.ic_id[0],8,16,QChar('0')).toUpper();
            // str.sprintf("%08X%08X%08X", dev_data.ic_id[2], dev_data.ic_id[1], dev_data.ic_id[0]);
            item->setText(str);

            item = p_table_widget->item(5, 1);
            str = QString("%1").arg(dev_data.ic_id[3],8,16,QChar('0')).toUpper();
            // str.sprintf("%08X", dev_data.ic_id[3]);
            item->setText(str);

            item = p_table_widget->item(6, 1);
            str = QString("%1").arg(dev_data.modbus_addr);
            // str.sprintf("%d", dev_data.modbus_addr);
            item->setText(str);
        } else {
            item = p_table_widget->item(2, 1);
            str = tr("");
            item->setText(str);

            item = p_table_widget->item(3, 1);
            str = tr("");
            item->setText(str);

            item = p_table_widget->item(4, 1);
            str = tr("");
            item->setText(str);

            item = p_table_widget->item(5, 1);
            str = tr("");
            item->setText(str);

            item = p_table_widget->item(6, 1);
            str = tr("");
            item->setText(str);
        }
    } else {
        QString str = tr("");
        QTableWidgetItem *item;

        item = p_table_widget->item(0, 1);
        item->setText(str);

        item = p_table_widget->item(1, 1);
        item->setText(str);

        item = p_table_widget->item(2, 1);
        item->setText(str);

        item = p_table_widget->item(3, 1);
        item->setText(str);

        item = p_table_widget->item(4, 1);
        item->setText(str);

        item = p_table_widget->item(5, 1);
        item->setText(str);

        item = p_table_widget->item(6, 1);
        item->setText(str);
    }
    dev_mutex.unlock();
}

void MainWindow::KeyDisplay(void)
{
    bool flag = true;
    const QString up_color_str("color: black;background-color: white");
    const QString down_color_str("color: black;background-color: springgreen");

    if (dev_data.test_result != 0) {
        return;
    }
    dev_mutex.lock();

    if (dev_data.touch[0]) {
        ui->label_key1->setStyleSheet(down_color_str);
    }else{
        ui->label_key1->setStyleSheet(up_color_str);
        flag = false;
    }

    if (dev_data.touch[1]) {
        ui->label_key2->setStyleSheet(down_color_str);
    }else{
        ui->label_key2->setStyleSheet(up_color_str);
        flag = false;
    }

    if (dev_data.touch[2]) {
        ui->label_key3->setStyleSheet(down_color_str);
    }else{
        ui->label_key3->setStyleSheet(up_color_str);
        flag = false;
    }

    if (dev_data.touch[3]) {
        ui->label_key4->setStyleSheet(down_color_str);
    }else{
        ui->label_key4->setStyleSheet(up_color_str);
        flag = false;
    }

    if (dev_data.touch[4]) {
        ui->label_key5->setStyleSheet(down_color_str);
    }else{
        ui->label_key5->setStyleSheet(up_color_str);
        flag = false;
    }

    dev_mutex.unlock();
}

void MainWindow::LcdDisplay(void)
{
    //ui->lcdNumber_4->display(QString("%1").arg(Para.PH));
//    const QString err_color_str("color: black;background-color: red");
//    const QString ok_color_str("color: black;background-color: springgreen");
    //dev_data.ph = 7.1;
//    if ((dev_data.ph >= 7.0) && (dev_data.ph <= 7.2)) {
//        ui->lcdNumber_4->setStyleSheet(ok_color_str);
//    } else {
//        ui->lcdNumber_4->setStyleSheet(err_color_str);
//    }
    dev_mutex.lock();
    if(m_phEnable)
    {
        ui->lcdNumber_4->display(QString::number(dev_data.ph,'f',1));
    }
    else
    {
        ui->lcdNumber_4->display(QString::number(0,'f',1));
    }

    if(m_orpEnable)
    {
        ui->lcdNumber_3->display(QString::number(dev_data.orp,'f',0));
    }
    else
    {
        ui->lcdNumber_3->display(QString::number(0,'f',0));
    }

    if(m_waterTempEanble)
    {
        ui->lcdNumber_2->display(QString::number(dev_data.waterTemp,'f',1));
    }
    else
    {
        ui->lcdNumber_2->display(QString::number(0,'f',1));
    }
    ui->lcdNumber->display(QString::number(dev_data.bodyTemp,'f',1));
    ui->lcdNumber_5->display(QString::number(dev_data.sj,'f',1));
    ui->lcdNumber_6->display(QString::number(dev_data.si,'f',1));
    ui->lcdNumber_7->display(QString::number(dev_data.sv,'f',1));
    ui->lcdNumber_8->display(QString::number(dev_data.size,'f',0));
    dev_mutex.unlock();
}


void MainWindow::lcd_display()
{
    //ui->lcdNumber_4->display(QString("%1").arg(Para.PH));
    const QString err_color_str("color: black;background-color: red");
    const QString ok_color_str("color: black;background-color: springgreen");
    dev_data.ph = 7.1;
    if ((dev_data.ph >= 7.0) && (dev_data.ph <= 7.2)) {
        ui->lcdNumber_4->setStyleSheet(ok_color_str);
    } else {
        ui->lcdNumber_4->setStyleSheet(err_color_str);
    }
    ui->lcdNumber_4->display(QString::number(dev_data.ph,'f',1));


    ui->lcdNumber_3->display(QString::number(dev_data.orp,'f',0));
    ui->lcdNumber_2->display(QString::number(dev_data.waterTemp,'f',1));
    ui->lcdNumber->display(QString::number(dev_data.bodyTemp,'f',1));
    ui->lcdNumber_5->display(QString::number(dev_data.sj,'f',1));
    ui->lcdNumber_6->display(QString::number(dev_data.si,'f',1));
    ui->lcdNumber_7->display(QString::number(dev_data.sv,'f',1));
    ui->lcdNumber_8->display(QString::number(dev_data.size,'f',0));
}

void MainWindow::clear_lcd_display()
{
    ui->lcdNumber_4->display(QString::number(0,'f',1));
    ui->lcdNumber_3->display(QString::number(0,'f',0));
    ui->lcdNumber_2->display(QString::number(0,'f',1));
    ui->lcdNumber->display(QString::number(0,'f',1));
    ui->lcdNumber_5->display(QString::number(0,'f',1));
    ui->lcdNumber_6->display(QString::number(0,'f',1));
    ui->lcdNumber_7->display(QString::number(0,'f',1));
    ui->lcdNumber_8->display(QString::number(0,'f',0));
}

void MainWindow::InitLcdDisplay(void)
{
    ui->lcdNumber_4->setStyleSheet("background-color: white");
    ui->lcdNumber_4->display(QString::number(0,'f',1));

    ui->lcdNumber_3->setStyleSheet("background-color: white");
    ui->lcdNumber_3->display(QString::number(0,'f',0));

    ui->lcdNumber_2->setStyleSheet("background-color: white");
    ui->lcdNumber_2->display(QString::number(0,'f',1));

    ui->lcdNumber->setStyleSheet("background-color: white");
    ui->lcdNumber->display(QString::number(0,'f',1));

    ui->lcdNumber_5->setStyleSheet("background-color: white");
    ui->lcdNumber_5->display(QString::number(0,'f',1));

    ui->lcdNumber_6->setStyleSheet("background-color: white");
    ui->lcdNumber_6->display(QString::number(0,'f',1));

    ui->lcdNumber_7->setStyleSheet("background-color: white");
    ui->lcdNumber_7->display(QString::number(0,'f',1));

    ui->lcdNumber_8->setStyleSheet("background-color: white");
    ui->lcdNumber_8->display(QString::number(0,'f',0));
}

void MainWindow::InitTextBrowser(void)
{
    ui->textBrowser->setFont(QFont(SYS_FONT_TYPE, 16));
    ui->textBrowser->setStyleSheet("background-color: white");
    //ui->textBrowser->clear();
    ui->textBrowser->setText("测试步骤：\r\n"
                             "a.请将打印工具接入电脑USB口\r\n"
                             "b.选择端口号\r\n"
                             "c.点击'打开串口'\r\n"
                             "d.请确认测试硬件已连接\r\n");
}

void MainWindow::ORP_Enable_Set(bool s)
{
    m_orpEnable = s;
}
void MainWindow::PH_Enable_Set(bool s)
{
    m_phEnable = s;
}
void MainWindow::WaterTemp_Enable_Set(bool s)
{
    m_waterTempEanble = s;
}


// 目前nb必须为16的倍数
//int MainWindow::
int ModbusReadInputBits(int addr, int nb, uint8_t *dest)
{
    int ret = 0;
    uint8_t buf[512] = {0};
    uint16_t crc = 0x0;
    int len = 0;
    int timeout = 0;
    uint8_t dev_id;
    uint8_t fun_num;
    uint8_t bytes;
    uint8_t oft = 0;
    uint8_t mod = 0;
    uint16_t tmp_val;
    QByteArray recv_buf;

    buf[0] = dev_data.dev_id;  // 暂时默认为8号设备
    buf[1] = 0x02;  // modbus 0x02功能码
    buf[2] = (addr >> 0x08) & 0xFF;
    buf[3] = addr & 0xFF;
    buf[4] = (nb >> 0x08) & 0xFF;
    buf[5] = nb & 0xFF;
    crc = CRC16(buf, 6);
    buf[6] = (crc >> 0x08) & 0xFF;
    buf[7] = crc & 0xFF;
    len = 8;

    ret = SendData(buf, len);

    while ((timeout <= 300) && (GetSerialPortErr() == 0)) {
        recv_buf = GetSerialPortRecvBuf();
        if (recv_buf.size() >= 3) {
            fun_num = recv_buf[1] & 0xFF;
            if (fun_num == 0x02) {  // 没有错误码
                bytes = recv_buf[2] & 0xFF;
                len = 3+bytes+2;
                if (recv_buf.size() >= len) {
                    crc = (recv_buf[len-2] << 0x08) | (recv_buf[len-1] & 0xFF);
                    if (CRC16((uint8_t *)recv_buf.data(), len - 2) == crc) {    // crc校验正确
                        oft = 3;    // 从有效数据字节开始
                        // 下位机以16bit位单位读取应答，且为小端模式
                        for (int i = 0; i < bytes; i += 2) {
                            tmp_val = (recv_buf[3+i+1] << 0x08) | (recv_buf[3+i] & 0xFF);
                            for (int j = 0; j < 16; j++) {
                                *dest = (tmp_val & 0x01);
                                dest++;
                                tmp_val = (tmp_val >> 0x01);
                            }
                        }
//                        for (int i = 0; i < nb; ) {
//                            *dest = ((recv_buf[oft] >> mod) & 0x01) ? 1 : 0;
//                            dest++;
//                            mod = (++i % 8);
//                            if (mod == 0) {
//                                oft++;
//                            }
//                        }
//                        for (int i= 0; i < len; i++) {
//                            qDebug("buf[%d]:%02x", i, recv_buf[i] & 0xFF);
//                        }
                        //qDebug("timeout:%d", timeout);
                        ret = nb;                        
                        //return ret;
                    }
                    ClearSerialPortRecvBuf();
                    break;
                }
            } else {
                ClearSerialPortRecvBuf();
                break;
            }
        }
        OsSleep(10);
        timeout += 10;
    }
    if (timeout > 300) {
        ClearSerialPortRecvBuf();
    }
    return ret;
}

int ModbusWriteFactoryRegisters(int addr, int nb, uint16_t *val)
{
    int ret = 0;
    uint8_t buf[512] = {0};
    uint16_t crc = 0x0;
    int len = 0;
    int timeout = 0;
    uint8_t dev_id;
    uint8_t fun_num;
    uint8_t bytes;
    uint16_t tmp_val;
    QByteArray recv_buf;

    buf[0] = dev_data.dev_id;  // 暂时默认为8号设备
    buf[1] = 0x08;  // modbus 0x08功能码
    buf[2] = (addr >> 0x08) & 0xFF;
    buf[3] = addr & 0xFF;
    buf[4] = 0x00;
    buf[5] = 0x03;
    buf[6] = 0x06;
    buf[7] = (val[0] >> 8) & 0xFF;
    buf[8] = val[0] & 0xFF;
    buf[9] = (val[1] >> 8) & 0xFF;
    buf[10] = val[1] & 0xFF;
    buf[11] = (val[2] >> 8) & 0xFF;
    buf[12] = val[2] & 0xFF;
    crc = CRC16(buf, 13);
    buf[13] = (crc >> 0x08) & 0xFF;
    buf[14] = crc & 0xFF;
    len = 15;

    ret = SendData(buf, len);
    if (ret != len) {
        ret = 0;
        return ret;
    }
    ret = 0;

    while ((timeout <= 300) && (GetSerialPortErr() == 0)) {
        recv_buf = GetSerialPortRecvBuf();
        if (recv_buf.size() >= 3) {
            fun_num = recv_buf[1] & 0xFF;
            if (fun_num == 0x08) {  // 没有错误码
                bytes = 4;
                len = 2+bytes+2;
                if (recv_buf.size() >= len) {
                    crc = (recv_buf[len-2] << 0x08) | (recv_buf[len-1] & 0xFF);
                    if (CRC16((uint8_t *)recv_buf.data(), len - 2) == crc) {    // crc校验正确
//                        for (int i= 0; i < len; i++) {
//                            qDebug("buf[%d]:%02x", i, recv_buf[i] & 0xFF);
//                        }
                        //qDebug("timeout:%d", timeout);
                        ret = nb;

                        //return ret;
                    }
                    ClearSerialPortRecvBuf();
                    break;
                }
            } else {
                ClearSerialPortRecvBuf();
                break;
            }
        }
        OsSleep(10);
        timeout += 10;
    }
    if (timeout > 300) {
        ClearSerialPortRecvBuf();
    }
    return ret;
}

int ModbusReadFactoryRegisters(int addr, int nb, uint16_t *dest)
{
    int ret = 0;
    uint8_t buf[512] = {0};
    uint16_t crc = 0x0;
    int len = 0;
    int timeout = 0;
    uint8_t dev_id;
    uint8_t fun_num;
    uint8_t bytes;
    uint16_t tmp_val;
    QByteArray recv_buf;

    buf[0] = dev_data.dev_id;  // 暂时默认为8号设备
    buf[1] = 0x07;  // modbus 0x07功能码
    buf[2] = (addr >> 0x08) & 0xFF;
    buf[3] = addr & 0xFF;
    buf[4] = (nb >> 0x08) & 0xFF;
    buf[5] = nb & 0xFF;
    crc = CRC16(buf, 6);
    buf[6] = (crc >> 0x08) & 0xFF;
    buf[7] = crc & 0xFF;
    len = 8;

    ret = SendData(buf, len);
    if (ret != len) {
        ret = 0;
        return ret;
    }
    ret = 0;

    while ((timeout <= 300) && (GetSerialPortErr() == 0)) {
        recv_buf = GetSerialPortRecvBuf();
        if (recv_buf.size() >= 3) {
            fun_num = recv_buf[1] & 0xFF;
            if (fun_num == 0x07) {  // 没有错误码
                bytes = recv_buf[2] & 0xFF;
                len = 3+bytes+2;
                //qDebug("len:%d", len);
                if (recv_buf.size() >= len) {
                    crc = (recv_buf[len-2] << 0x08) | (recv_buf[len-1] & 0xFF);
                    if (CRC16((uint8_t *)recv_buf.data(), len - 2) == crc) {    // crc校验正确
                        for (int i = 0; i < bytes; i += 2) {
                            tmp_val = (recv_buf[3+i] << 0x08) | (recv_buf[3+i+1] & 0xFF);
                            *dest = tmp_val;
                            dest++;
                        }
//                        for (int i= 0; i < len; i++) {
//                            qDebug("buf[%d]:%02x", i, recv_buf[i] & 0xFF);
//                        }
                        ret = nb;
                        //qDebug("timeout:%d", timeout);
                        //return ret;
                    }
                    ClearSerialPortRecvBuf();
                    break;
                }
            } else {
                ClearSerialPortRecvBuf();
                break;
            }
        }
        OsSleep(10);
        timeout += 10;
    }
    if (timeout > 300) {
        ClearSerialPortRecvBuf();
    }
    return ret;
}

//int MainWindow::
int ModbusReadRegisters(int addr, int nb, uint16_t *dest)
{
    int ret = 0;
    uint8_t buf[512] = {0};
    uint16_t crc = 0x0;
    int len = 0;
    int timeout = 0;
    uint8_t dev_id;
    uint8_t fun_num;
    uint8_t bytes;
    uint16_t tmp_val;
    QByteArray recv_buf;

    buf[0] = dev_data.dev_id;  // 暂时默认为8号设备
    buf[1] = 0x03;  // modbus 0x03功能码
    buf[2] = (addr >> 0x08) & 0xFF;
    buf[3] = addr & 0xFF;
    buf[4] = (nb >> 0x08) & 0xFF;
    buf[5] = nb & 0xFF;
    crc = CRC16(buf, 6);
    buf[6] = (crc >> 0x08) & 0xFF;
    buf[7] = crc & 0xFF;
    len = 8;

    ret = SendData(buf, len);
    if (ret != len) {
        ret = 0;
        return ret;
    }
    ret = 0;

    while ((timeout <= 300) && (GetSerialPortErr() == 0)) {
        recv_buf = GetSerialPortRecvBuf();
        if (recv_buf.size() >= 3) {
            fun_num = recv_buf[1] & 0xFF;
            if (fun_num == 0x03) {  // 没有错误码
                bytes = recv_buf[2] & 0xFF;
                len = 3+bytes+2;
                if (recv_buf.size() >= len) {
                    crc = (recv_buf[len-2] << 0x08) | (recv_buf[len-1] & 0xFF);
                    if (CRC16((uint8_t *)recv_buf.data(), len - 2) == crc) {    // crc校验正确
                        for (int i = 0; i < bytes; i += 2) {
                            tmp_val = (recv_buf[3+i] << 0x08) | (recv_buf[3+i+1] & 0xFF);
                            *dest = tmp_val;
                            dest++;
                        }
//                        for (int i= 0; i < len; i++) {
//                            qDebug("buf[%d]:%02x", i, recv_buf[i] & 0xFF);
//                        }
                        ret = nb;
                        //qDebug("timeout:%d", timeout);                        
                        //return ret;
                    }
                    ClearSerialPortRecvBuf();
                    break;
                }
            } else {
                ClearSerialPortRecvBuf();
                break;
            }
        }
        OsSleep(10);
        timeout += 10;
    }
    if (timeout > 300) {
        ClearSerialPortRecvBuf();
    }
    return ret;
}

//int MainWindow::
int ModbusWriteRegister(int addr, uint16_t val)
{
    int ret = 0;
    uint8_t buf[512] = {0};
    uint16_t crc = 0x0;
    int len = 0;
    int timeout = 0;
    uint8_t dev_id;
    uint8_t fun_num;
    uint8_t bytes;
    uint16_t tmp_val;
    QByteArray recv_buf;

    buf[0] = dev_data.dev_id;  // 暂时默认为8号设备
    buf[1] = 0x06;  // modbus 0x06功能码
    buf[2] = (addr >> 0x08) & 0xFF;
    buf[3] = addr & 0xFF;
    buf[4] = (val >> 0x08) & 0xFF;
    buf[5] = val & 0xFF;
    crc = CRC16(buf, 6);
    buf[6] = (crc >> 0x08) & 0xFF;
    buf[7] = crc & 0xFF;
    len = 8;

    ret = SendData(buf, len);
    if (ret != len) {
        ret = 0;
        return ret;
    }
    ret = 0;

    while ((timeout <= 300) && (GetSerialPortErr() == 0)) {
        recv_buf = GetSerialPortRecvBuf();
        if (recv_buf.size() >= 3) {
            fun_num = recv_buf[1] & 0xFF;
            if (fun_num == 0x06) {  // 没有错误码
                bytes = 4;
                len = 2+bytes+2;
                if (recv_buf.size() >= len) {
                    crc = (recv_buf[len-2] << 0x08) | (recv_buf[len-1] & 0xFF);
                    if (CRC16((uint8_t *)recv_buf.data(), len - 2) == crc) {    // crc校验正确
//                        for (int i= 0; i < len; i++) {
//                            qDebug("buf[%d]:%02x", i, recv_buf[i] & 0xFF);
//                        }
                        //qDebug("timeout:%d", timeout);
                        ret = 1;

                        //return ret;
                    }
                    ClearSerialPortRecvBuf();
                    break;
                }
            } else {
                ClearSerialPortRecvBuf();
                break;
            }
        }
        OsSleep(10);
        timeout += 10;
    }
    if (timeout > 300) {
        ClearSerialPortRecvBuf();
    }
    return ret;
}

//int MainWindow::
int ModbusReadInputRegisters(int addr, int nb, uint16_t *dest)
{
    int ret = 0;
    uint8_t buf[512] = {0};
    uint16_t crc = 0x0;
    int len = 0;
    int timeout = 0;
    uint8_t dev_id;
    uint8_t fun_num;
    uint8_t bytes;
    uint16_t tmp_val;
    QByteArray recv_buf;

    buf[0] = dev_data.dev_id;  // 暂时默认为8号设备
    buf[1] = 0x04;  // modbus 0x04功能码
    buf[2] = (addr >> 0x08) & 0xFF;
    buf[3] = addr & 0xFF;
    buf[4] = (nb >> 0x08) & 0xFF;
    buf[5] = nb & 0xFF;
    crc = CRC16(buf, 6);
    buf[6] = (crc >> 0x08) & 0xFF;
    buf[7] = crc & 0xFF;
    len = 8;

    ret = SendData(buf, len);
    if (ret != len) {
        ret = 0;
        return ret;
    }
    ret = 0;

    while ((timeout <= 300) && (GetSerialPortErr() == 0)) {
        recv_buf = GetSerialPortRecvBuf();
        if (recv_buf.size() >= 3) {
            fun_num = recv_buf[1] & 0xFF;
            if (fun_num == 0x04) {  // 没有错误码
                bytes = recv_buf[2] & 0xFF;
                len = 3+bytes+2;

                if (recv_buf.size() >= len) {
                    crc = (recv_buf[len-2] << 0x08) | (recv_buf[len-1] & 0xFF);
                    if (CRC16((uint8_t *)recv_buf.data(), len - 2) == crc) {    // crc校验正确
                        for (int i = 0; i < bytes; i += 2) {
                            tmp_val = (recv_buf[3+i] << 0x08) | (recv_buf[3+i+1] & 0xFF);
                            *dest = tmp_val;
                            dest++;
                        }
                        //qDebug("timeout:%d", timeout);
//                        for (int i= 0; i < len; i++) {
//                            qDebug("buf[%d]:%02x", i, recv_buf[i] & 0xFF);
//                        }
                        ret = nb;

                        //return ret;
                    }
                    ClearSerialPortRecvBuf();
                    break;
                }
            } else {
                ClearSerialPortRecvBuf();
                break;
            }
        }
        OsSleep(10);
        timeout += 10;
    }
    if (timeout > 300) {
        ClearSerialPortRecvBuf();
    }
    return ret;
}

void MainWindow::UpdateDataDisplay(void)
{
    const QString pass_color_str("color: black;background-color: springgreen");
    const QString fail_color_str("color: black;background-color: red");

    InfoDisplay();

    judge_time -= 200;
    if (judge_time < 0) {
        judge_time = 0;
    }
    //qDebug("judge_time:%d", judge_time);
    JudgeTimeDisplay();
    SoftVersionDisplay();
    ProductTypeDisplay();
    KeyDisplay();
    LcdDisplay();

    dev_mutex.lock();
    if (dev_data.wifi) {
        ui->label_wifi_state->setText("ON");
    } else {
        ui->label_wifi_state->setText("OFF");
    }

    if (dev_data.point) {
        ui->label_point_state->setText("ON");
    } else {
        ui->label_point_state->setText("OFF");
    }

    if (dev_data.time) {
        ui->label_time_state->setText("ON");
    } else {
        ui->label_time_state->setText("OFF");
    }

    if (dev_data.rs485) {
        ui->label_rs485_state->setText("ON");
    } else {
        ui->label_rs485_state->setText("OFF");
    }

    if (dev_data.rc) {
        ui->label_rc_state->setText("ON");
    } else {
        ui->label_rc_state->setText("OFF");
    }

    if (dev_data.sr) {
        ui->label_sr_state->setText("ON");
    } else {
        ui->label_sr_state->setText("OFF");
    }


    if (!dev_data.buzzer) {
        //ui->label_buzzer->setStyleSheet(fail_color_str);
    } else {
        ui->label_buzzer->setStyleSheet(pass_color_str);
    }

    if (!dev_data.motor) {
        //ui->label_motor->setStyleSheet(fail_color_str);
    } else {
        ui->label_motor->setStyleSheet(pass_color_str);
    }

    dev_mutex.unlock();
    //flag = !flag;
}

void MainWindow::table_widget_cell_clicked(int row, int column)
{
    int res;

    if (1) {//(test_step == 1) && com.connect_flag && (GetSerialPortErr() == 0)) {
//        if ((dev_data.soft_ver_i < 0x000A002A) ||
//            (dev_data.product_type == PRODUCT_TYPE_L)) {// 10.0.40之前返回
//            return ;
//        }
        SettingDialog dlg;

        dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);
        res = dlg.exec();
        switch (dev_data.setting_cell_model) {
        case 10: SetElectrolyzerIndex(0); break;
        case 20: SetElectrolyzerIndex(2); break;
        case 30: SetElectrolyzerIndex(3); break;
        case 40: SetElectrolyzerIndex(4); break;
        default : SetElectrolyzerIndex(0); break;
        }
        ui->comboBox_control_mode->setCurrentIndex(dev_data.setting_control_mode);
    }
}

void MainWindow::TestResultShow(uint32_t mode)
{
    const QString pass_color_str("color: black;background-color: springgreen");
    const QString fail_color_str("color: black;background-color: red");
    QPalette label_palette;
    QColor b_color = ui->label_size_select->palette().color(ui->label_size_select->backgroundRole());

    label_palette.setColor(QPalette::Window, b_color);

    if (mode == 0) {
        qDebug("mode 0");
        ui->label_test_mode->setStyleSheet(pass_color_str);
//        ui->label_test_mode_2->setAutoFillBackground(true);
//        ui->label_test_mode_2->setPalette(label_palette);
        ui->label_test_mode_2->setStyleSheet("background-color: transparent;");
//        ui->label_test_mode_3->setAutoFillBackground(true);
//        ui->label_test_mode_3->setPalette(label_palette);
        ui->label_test_mode_3->setStyleSheet("background-color: transparent;");
//        ui->label_test_mode_4->setAutoFillBackground(true);
//        ui->label_test_mode_4->setPalette(label_palette);
        ui->label_test_mode_4->setStyleSheet("background-color: transparent;");
//        ui->label_test_mode_5->setAutoFillBackground(true);
//        ui->label_test_mode_5->setPalette(label_palette);
        ui->label_test_mode_5->setStyleSheet("background-color: transparent;");
//        ui->label_test_mode_6->setAutoFillBackground(true);
//        ui->label_test_mode_6->setPalette(label_palette);
        ui->label_test_mode_6->setStyleSheet("background-color: transparent;");
//        ui->label_test_mode_7->setAutoFillBackground(true);
//        ui->label_test_mode_7->setPalette(label_palette);
        ui->label_test_mode_7->setStyleSheet("background-color: transparent;");
//        ui->label_test_mode_8->setAutoFillBackground(true);
//        ui->label_test_mode_8->setPalette(label_palette);
        ui->label_test_mode_8->setStyleSheet("background-color: transparent;");
//        ui->label_test_result->setAutoFillBackground(true);
//        ui->label_test_result->setPalette(label_palette);
        ui->label_test_result->setStyleSheet("background-color: transparent;");
        ui->label_test_result->setText(tr(""));
//        ui->label_test_result_2->setAutoFillBackground(true);
//        ui->label_test_result_2->setPalette(label_palette);
        ui->label_test_result_2->setStyleSheet("background-color: transparent;");
//        ui->label_test_result_3->setAutoFillBackground(true);
//        ui->label_test_result_3->setPalette(label_palette);
        ui->label_test_result_3->setStyleSheet("background-color: transparent;");
//        ui->label_test_result_4->setAutoFillBackground(true);
//        ui->label_test_result_4->setPalette(label_palette);
        ui->label_test_result_4->setStyleSheet("background-color: transparent;");
//        ui->label_test_result_5->setAutoFillBackground(true);
//        ui->label_test_result_5->setPalette(label_palette);
        ui->label_test_result_5->setStyleSheet("background-color: transparent;");
//        ui->label_test_result_6->setAutoFillBackground(true);
//        ui->label_test_result_6->setPalette(label_palette);
        ui->label_test_result_6->setStyleSheet("background-color: transparent;");
//        ui->label_test_result_7->setAutoFillBackground(true);
//        ui->label_test_result_7->setPalette(label_palette);
        ui->label_test_result_7->setStyleSheet("background-color: transparent;");
//        ui->label_test_result_8->setAutoFillBackground(true);
//        ui->label_test_result_8->setPalette(label_palette);
        ui->label_test_result_8->setStyleSheet("background-color: transparent;");
    } else if (mode == 1) {
        ui->label_test_mode->setStyleSheet(pass_color_str);
        ui->label_test_mode_2->show();
        ui->label_test_mode_2->setStyleSheet(pass_color_str);
        ui->label_test_mode_3->show();
        ui->label_test_mode_3->setStyleSheet(pass_color_str);
        ui->label_test_mode_4->show();
        ui->label_test_mode_4->setStyleSheet(pass_color_str);
        ui->label_test_mode_5->show();
        ui->label_test_mode_5->setStyleSheet(pass_color_str);
        ui->label_test_mode_6->show();
        ui->label_test_mode_6->setStyleSheet(pass_color_str);
        ui->label_test_mode_7->show();
        ui->label_test_mode_7->setStyleSheet(pass_color_str);
        ui->label_test_mode_8->show();
        ui->label_test_mode_8->setStyleSheet(pass_color_str);
        ui->label_test_result->show();
        ui->label_test_result->setText(tr("PASS"));
        ui->label_test_result->setStyleSheet(pass_color_str);
        ui->label_test_result_2->show();
        ui->label_test_result_2->setStyleSheet(pass_color_str);
        ui->label_test_result_3->show();
        ui->label_test_result_3->setStyleSheet(pass_color_str);
        ui->label_test_result_4->show();
        ui->label_test_result_4->setStyleSheet(pass_color_str);
        ui->label_test_result_5->show();
        ui->label_test_result_5->setStyleSheet(pass_color_str);
        ui->label_test_result_6->show();
        ui->label_test_result_6->setStyleSheet(pass_color_str);
        ui->label_test_result_7->show();
        ui->label_test_result_7->setStyleSheet(pass_color_str);
        ui->label_test_result_8->show();
        ui->label_test_result_8->setStyleSheet(pass_color_str);
    } else if (mode == 2) {
        ui->label_test_mode->setStyleSheet(fail_color_str);
        ui->label_test_mode_2->show();
        ui->label_test_mode_2->setStyleSheet(fail_color_str);
        ui->label_test_mode_3->show();
        ui->label_test_mode_3->setStyleSheet(fail_color_str);
        ui->label_test_mode_4->show();
        ui->label_test_mode_4->setStyleSheet(fail_color_str);
        ui->label_test_mode_5->show();
        ui->label_test_mode_5->setStyleSheet(fail_color_str);
        ui->label_test_mode_6->show();
        ui->label_test_mode_6->setStyleSheet(fail_color_str);
        ui->label_test_mode_7->show();
        ui->label_test_mode_7->setStyleSheet(fail_color_str);
        ui->label_test_mode_8->show();
        ui->label_test_mode_8->setStyleSheet(fail_color_str);
        ui->label_test_result->show();
        ui->label_test_result->setText(tr("FAIL"));
        ui->label_test_result->setStyleSheet(fail_color_str);
        ui->label_test_result_2->show();
        ui->label_test_result_2->setStyleSheet(fail_color_str);
        ui->label_test_result_3->show();
        ui->label_test_result_3->setStyleSheet(fail_color_str);
        ui->label_test_result_4->show();
        ui->label_test_result_4->setStyleSheet(fail_color_str);
        ui->label_test_result_5->show();
        ui->label_test_result_5->setStyleSheet(fail_color_str);
        ui->label_test_result_6->show();
        ui->label_test_result_6->setStyleSheet(fail_color_str);
        ui->label_test_result_7->show();
        ui->label_test_result_7->setStyleSheet(fail_color_str);
        ui->label_test_result_8->show();
        ui->label_test_result_8->setStyleSheet(fail_color_str);
    }
}

void MainWindow::TestDataResultDisplay(void)
{
    bool flag = true;
    const QString pass_color_str("color: black;background-color: springgreen");
    const QString fail_color_str("color: black;background-color: red");
    float min, max;

    dev_mutex.lock();

    if (dev_data.touch[0]) {
        ui->label_key1->setStyleSheet(pass_color_str);
    }else{
        ui->label_key1->setStyleSheet(fail_color_str);
        flag = false;
    }

    if (dev_data.touch[1]) {
        ui->label_key2->setStyleSheet(pass_color_str);
    }else{
        ui->label_key2->setStyleSheet(fail_color_str);
        flag = false;
    }

    if (dev_data.touch[2]) {
        ui->label_key3->setStyleSheet(pass_color_str);
    }else{
        ui->label_key3->setStyleSheet(fail_color_str);
        flag = false;
    }

    if (dev_data.touch[3]) {
        ui->label_key4->setStyleSheet(pass_color_str);
    }else{
        ui->label_key4->setStyleSheet(fail_color_str);
        flag = false;
    }

    if (dev_data.touch[4]) {
        ui->label_key5->setStyleSheet(pass_color_str);
    }else{
        ui->label_key5->setStyleSheet(fail_color_str);
        flag = false;
    }

    if (!flag) {
        ui->label_key->setStyleSheet(fail_color_str);
    } else {
        ui->label_key->setStyleSheet(pass_color_str);
    }

    if (((dev_data.ph < 4.0) || (dev_data.ph > 6.5)) && m_phEnable)
    {
        ui->lcdNumber_4->setStyleSheet(fail_color_str);
    }
    else
    {
        ui->lcdNumber_4->setStyleSheet(pass_color_str);
    }

    if (((dev_data.orp < 615) || (dev_data.orp > 718)) && m_orpEnable)
    {
        ui->lcdNumber_3->setStyleSheet(fail_color_str);
    }
    else
    {
        ui->lcdNumber_3->setStyleSheet(pass_color_str);
    }

    if (((dev_data.waterTemp < 26.0) || (dev_data.waterTemp > 35.0)) && m_waterTempEanble)
    {
        ui->lcdNumber_2->setStyleSheet(fail_color_str);
    }
    else
    {
        ui->lcdNumber_2->setStyleSheet(pass_color_str);
    }

    if (test_mode == TEST_MODE_PCBA) {
        if ((dev_data.bodyTemp < 50.0) || (dev_data.bodyTemp > 58.0)) {
            ui->lcdNumber->setStyleSheet(fail_color_str);
        } else {
            ui->lcdNumber->setStyleSheet(pass_color_str);
        }
    } else {
        if ((dev_data.bodyTemp < 12.0) || (dev_data.bodyTemp > 80.0)) {
            ui->lcdNumber->setStyleSheet(fail_color_str);
        } else {
            ui->lcdNumber->setStyleSheet(pass_color_str);
        }
    }

    if (test_mode == TEST_MODE_PRODUCT) {
        min = electrolytic_sj_range[ui->comboBox->currentIndex()][0];
        max = electrolytic_sj_range[ui->comboBox->currentIndex()][1];
    } else {
        min = 0.4;
        max = 3.3;
    }

    if ((dev_data.sj < min) || (dev_data.sj > max)) {
        ui->lcdNumber_5->setStyleSheet(fail_color_str);
    } else {
        ui->lcdNumber_5->setStyleSheet(pass_color_str);
    }

    if (test_mode == TEST_MODE_PRODUCT) {
        min = electrolytic_si_range[ui->comboBox->currentIndex()][0];
        max = electrolytic_si_range[ui->comboBox->currentIndex()][1];
    } else {
        min = 1.8;
        max = 10.2;
    }

    if ((dev_data.si < min) || (dev_data.si > max)) {
        ui->lcdNumber_6->setStyleSheet(fail_color_str);
    } else {
        ui->lcdNumber_6->setStyleSheet(pass_color_str);
    }

    if (test_mode == TEST_MODE_PRODUCT) {
        min = electrolytic_sv_range[ui->comboBox->currentIndex()][0];
        max = electrolytic_sv_range[ui->comboBox->currentIndex()][1];
    } else {
        min = 10.0;
        max = 24.0;
    }

    if ((dev_data.sv < min) || (dev_data.sv > max)) {
        ui->lcdNumber_7->setStyleSheet(fail_color_str);
    } else {
        ui->lcdNumber_7->setStyleSheet(pass_color_str);
    }

    if (!dev_data.point) {
        ui->label_point_state->setStyleSheet(fail_color_str);
        ui->label_wifi_state->setText("OFF");
    } else {
        ui->label_point_state->setStyleSheet(pass_color_str);
        ui->label_wifi_state->setText("ON");
    }

    if (!dev_data.wifi) {
        ui->label_wifi_state->setStyleSheet(fail_color_str);
        ui->label_wifi_state->setText("OFF");
    } else {
        ui->label_wifi_state->setStyleSheet(pass_color_str);
        ui->label_wifi_state->setText("ON");
    }

    if (!dev_data.rs485) {
        ui->label_rs485_state->setStyleSheet(fail_color_str);
        ui->label_rs485_state->setText("OFF");
    } else {
        ui->label_rs485_state->setStyleSheet(pass_color_str);
        ui->label_rs485_state->setText("ON");
    }

    if (!dev_data.time) {
        ui->label_time_state->setStyleSheet(fail_color_str);
        ui->label_time_state->setText("OFF");
    } else {
        ui->label_time_state->setStyleSheet(pass_color_str);
        ui->label_time_state->setText("ON");
    }

    if (!dev_data.sr) {
        ui->label_sr_state->setStyleSheet(fail_color_str);
        ui->label_sr_state->setText("OFF");
    } else {
        ui->label_sr_state->setStyleSheet(pass_color_str);
        ui->label_sr_state->setText("ON");
    }

    if (!dev_data.rc) {
        ui->label_rc_state->setStyleSheet(fail_color_str);
        ui->label_rc_state->setText("OFF");
    } else {
        ui->label_rc_state->setStyleSheet(pass_color_str);
        ui->label_rc_state->setText("ON");
    }

    if (((ui->comboBox->currentIndex() == 0) && (dev_data.size != ELECTROLYTIC_STRIP_1)) ||
        ((ui->comboBox->currentIndex() == 1) && (dev_data.size != ELECTROLYTIC_STRIP_2)) ||
        ((ui->comboBox->currentIndex() == 2) && (dev_data.size != ELECTROLYTIC_STRIP_3)) ||
        ((ui->comboBox->currentIndex() == 3) && (dev_data.size != ELECTROLYTIC_STRIP_4)) ||
        ((ui->comboBox->currentIndex() == 4) && (dev_data.size != ELECTROLYTIC_STRIP_5)) ||
        ((ui->comboBox->currentIndex() == 5) && (dev_data.size != ELECTROLYTIC_STRIP_6)) ||
        ((ui->comboBox->currentIndex() == 6) && (dev_data.size != ELECTROLYTIC_STRIP_7))) {
        ui->lcdNumber_8->setStyleSheet(fail_color_str);
    } else {
        ui->lcdNumber_8->setStyleSheet(pass_color_str);
    }

//    if (((ui->comboBox->currentIndex() == 0) && (dev_data.size != 9)) ||
//        ((ui->comboBox->currentIndex() == 1) && (dev_data.size != 16)) ||
//        ((ui->comboBox->currentIndex() == 2) && (dev_data.size != 21)) ||
//        ((ui->comboBox->currentIndex() == 3) && (dev_data.size != 26))) {
//        ui->lcdNumber_8->setStyleSheet(fail_color_str);
//    } else {
//        ui->lcdNumber_8->setStyleSheet(pass_color_str);
//    }

    if (!dev_data.buzzer) {
        ui->label_buzzer->setStyleSheet(fail_color_str);
    } else {
        ui->label_buzzer->setStyleSheet(pass_color_str);
    }

    if (!dev_data.motor) {
        ui->label_motor->setStyleSheet(fail_color_str);
    } else {
        ui->label_motor->setStyleSheet(pass_color_str);
    }

//    if (!dev_data.led) {
//        ui->label_led->setStyleSheet(fail_color_str);
//    } else {
//        ui->label_led->setStyleSheet(pass_color_str);
//    }
    dev_mutex.unlock();
    LcdDisplay();

}

//memset
void* memset(void *s,int ch,size_t n)
{
    if(s == nullptr)
    {
        return nullptr;
    }

    char *pdest = (char *)s;

    while(n-->0)
    {
        *pdest++ = ch;
    }

    return s;
}


//延时毫秒
void Delay_MSec(unsigned int msec)
{
    QEventLoop loop;//定义一个新的事件循环
    QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
    loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
}

QByteArray HexStringToByteArray(QString HexString)
{
    bool ok;
    QByteArray ret;
    HexString = HexString.trimmed();
    HexString = HexString.simplified();
    QStringList sl = HexString.split(" ");

    foreach (QString s, sl) {
        if(!s.isEmpty()) {
            char c = s.toInt(&ok,16)&0xFF;
            if(ok){
                ret.append(c);
            }else{
                qDebug()<<"非法的16进制字符："<<s;
            }
        }
    }
    return ret;
}

QString ByteArrayToHexString(QByteArray &ba)
{
    QDataStream out(&ba,QIODevice::ReadWrite);   //将str的数据 读到out里面去
    QString buf;
    while(!out.atEnd())
    {
        qint8 outChar = 0;
        out >> outChar;   //每次一个字节的填充到 outchar
        QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" ");   //2 字符宽度
        buf += str;
    }
    return buf;
}

QDemoThread::QDemoThread(QObject* parent) : QThread(parent)
{

}

QDemoThread::QDemoThread(thread_fun fun, void *arg) {
    m_fun  = fun;
    m_arg = arg;
}

QDemoThread::~QDemoThread()
{

}

void QDemoThread::run()
{
    flag = true;
    while(flag)
    {
        //qDebug()<< ""<< QThread::currentThreadId();
        m_fun(m_arg);
        msleep(200);
        //sleep(1);
    }
}

void QDemoThread::stop()
{
    flag = false;
    if(isRunning())
    {
        exit();
        wait();
    }
}

void MainWindow::on_help_btn_clicked()
{
    QString title_str;
    QString content_str;

    //msg.setWindowTitle("InverClear Chlorinator Control Mode Tool V1.0");
    title_str = TITLE_STR;
#if (EN_LANGUAGE_ENGLISH == 1)
    content_str = tr("1. Please select the correct communication port(COMx).\r\n");
    content_str += tr("2. Click the\"Open\"button to open the corresponding communication port.\r\n");
    content_str += tr("3. Create a wifi wireless hotspot named \"tuya_mdev_test\".\r\n");
    content_str += tr("4. Turn off the machine power and connect the peripheral interface.\r\n");
    content_str += tr("5. Turn on the machine power and enter the testing process.\r\n");
    content_str += tr("6. Click on the machine button and the water flow switch button.\r\n");
    content_str += tr("7. Please wait for the test results.\r\n");
    content_str += tr("8. Turn off the machine power and remove the peripheral interface.\r\n");
    content_str += tr("9. You can click on the table list area to enter settings(V10.0.40 later).\r\n");
    content_str += tr("10. You can set the \"modbus addr\",\"Control mode\",\"Cell model\".\r\n");
    content_str += tr("11. Click the \"Refresh\" button to update available communication ports.\r\n");
#else
    content_str = tr("1. 选中正确的通信端口（如：COMX）。\r\n");
    content_str += tr("2. 点击\"打开串口\"按钮，打开相应的通信端口。\r\n");
    content_str += tr("3. 通过RS485数据线连接目标待测机器，并观察测试结果。\r\n");
    content_str += tr("4. 点击列表区域，进入\"机器配置\"、\"电解片规格\"、\"MODBUS地址设置\"。\r\n");
    content_str += tr("5. 点击\"刷新\"按钮，刷新系统连接的可用通信端口。\r\n");
#endif
    MyMessageBox msg(QMessageBox::Question, title_str, content_str, QMessageBox::Ok);//(nullptr);
//    msg.setText(str);
//    msg.setIcon(QMessageBox::Question);
//    msg.addButton(QMessageBox::Ok);
    msg.exec();
}

